Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit eb26b0a

Browse files
author
Sauyon Lee
committed
SuspiciousCharacterInRegexp: Add fix for raw string literals
1 parent 52d253a commit eb26b0a

File tree

8 files changed

+42
-10
lines changed

8 files changed

+42
-10
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* The query "Suspicious characters in a regular expression" has been improved to recognize raw string literals, which should lead to fewer false positives.

ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ func broken(hostNames []byte) string {
99
} else {
1010
// This will be reached even if hostNames is exactly "forbidden.host.org",
1111
// because the literal backspace is not matched
12+
return ""
1213
}
1314
}

ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,10 @@ import DataFlow::PathGraph
2020
*/
2121
predicate containsEscapedCharacter(DataFlow::Node source, string character) {
2222
character in ["a", "b"] and
23-
exists(
23+
exists(StringLit s | s = source.asExpr() |
2424
// Search for `character` preceded by an odd number of backslashes:
25-
source
26-
.asExpr()
27-
.(BasicLit)
28-
.getText()
29-
.regexpFind("(?<=(^|[^\\\\])\\\\(\\\\{2}){0,10})" + character, _, _)
25+
exists(s.getText().regexpFind("(?<=(^|[^\\\\])\\\\(\\\\{2}){0,10})" + character, _, _)) and
26+
not s.isRaw()
3027
)
3128
}
3229

ql/src/Security/CWE-020/SuspiciousCharacterInRegexpGood.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ package main
33
import "regexp"
44

55
func fixed(hostNames []byte) string {
6-
var hostRe = regexp.MustCompile("\\bforbidden.host.org")
6+
var hostRe = regexp.MustCompile(`\bforbidden.host.org`)
77
if hostRe.Match(hostNames) {
88
return "Must not target forbidden.host.org"
99
} else {
1010
// hostNames definitely doesn't contain a word "forbidden.host.org", as "\\b"
1111
// is the start-of-word anchor, not a literal backspace.
12+
return ""
1213
}
1314
}

ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
edges
22
nodes
3+
| SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | semmle.label | "\\bforbidden.host.org" |
34
| test.go:8:21:8:34 | "hello\\aworld" | semmle.label | "hello\\aworld" |
45
| test.go:9:21:9:36 | "hello\\\\\\aworld" | semmle.label | "hello\\\\\\aworld" |
56
| test.go:10:21:10:34 | "hello\\bworld" | semmle.label | "hello\\bworld" |
67
| test.go:11:21:11:36 | "hello\\\\\\bworld" | semmle.label | "hello\\\\\\bworld" |
78
#select
9+
| SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | $@ used $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | A regular expression | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | here |
810
| test.go:8:21:8:34 | "hello\\aworld" | test.go:8:21:8:34 | "hello\\aworld" | test.go:8:21:8:34 | "hello\\aworld" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:8:21:8:34 | "hello\\aworld" | A regular expression | test.go:8:21:8:34 | "hello\\aworld" | here |
911
| test.go:9:21:9:36 | "hello\\\\\\aworld" | test.go:9:21:9:36 | "hello\\\\\\aworld" | test.go:9:21:9:36 | "hello\\\\\\aworld" | $@ used $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:9:21:9:36 | "hello\\\\\\aworld" | A regular expression | test.go:9:21:9:36 | "hello\\\\\\aworld" | here |
1012
| test.go:10:21:10:34 | "hello\\bworld" | test.go:10:21:10:34 | "hello\\bworld" | test.go:10:21:10:34 | "hello\\bworld" | $@ used $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:10:21:10:34 | "hello\\bworld" | A regular expression | test.go:10:21:10:34 | "hello\\bworld" | here |
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package main
2+
3+
import "regexp"
4+
5+
func broken(hostNames []byte) string {
6+
var hostRe = regexp.MustCompile("\bforbidden.host.org")
7+
if hostRe.Match(hostNames) {
8+
return "Must not target forbidden.host.org"
9+
} else {
10+
// This will be reached even if hostNames is exactly "forbidden.host.org",
11+
// because the literal backspace is not matched
12+
return ""
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package main
2+
3+
import "regexp"
4+
5+
func fixed(hostNames []byte) string {
6+
var hostRe = regexp.MustCompile(`\bforbidden.host.org`)
7+
if hostRe.Match(hostNames) {
8+
return "Must not target forbidden.host.org"
9+
} else {
10+
// hostNames definitely doesn't contain a word "forbidden.host.org", as "\\b"
11+
// is the start-of-word anchor, not a literal backspace.
12+
return ""
13+
}
14+
}

ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
package test
1+
package main
22

33
import "regexp"
44

5-
func test() {
5+
func main() {
66

77
// BAD: probably a mistake:
88
regexp.MustCompile("hello\aworld")
@@ -20,5 +20,6 @@ func test() {
2020
regexp.MustCompile("hello\010world")
2121
regexp.MustCompile("hello\u0008world")
2222
regexp.MustCompile("hello\U00000008world")
23-
23+
// GOOD: use of a raw string literal
24+
regexp.MustCompile(`hello\b\sworld`)
2425
}

0 commit comments

Comments
 (0)