Skip to content

Commit 5fcd663

Browse files
authored
Merge pull request #158 from esben-semmle/js/sharpen-regexp-injection
Approved by xiemaisi
2 parents 2d4f664 + b9d825b commit 5fcd663

File tree

4 files changed

+31
-2
lines changed

4 files changed

+31
-2
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Improvements to JavaScript analysis
2+
3+
## General improvements
4+
5+
## New queries
6+
7+
| **Query** | **Tags** | **Purpose** |
8+
|-----------------------------|-----------|--------------------------------------------------------------------|
9+
| *@name of query (Query ID)* | *Tags* |*Aim of the new query and whether it is enabled by default or not* |
10+
11+
## Changes to existing queries
12+
13+
| **Query** | **Expected impact** | **Change** |
14+
|--------------------------------|----------------------------|----------------------------------------------|
15+
| Regular expression injection | Fewer false-positive results | This rule now identifies calls to `String.prototype.search` with more precision. |
16+
17+
18+
## Changes to QL libraries

javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjection.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,13 @@ module RegExpInjection {
6969
mce.getReceiver().analyze().getAType() = TTString() and
7070
mce.getMethodName() = methodName |
7171
(methodName = "match" and this.asExpr() = mce.getArgument(0) and mce.getNumArgument() = 1) or
72-
(methodName = "search" and this.asExpr() = mce.getArgument(0) and mce.getNumArgument() = 1)
72+
(
73+
methodName = "search" and
74+
this.asExpr() = mce.getArgument(0) and
75+
mce.getNumArgument() = 1 and
76+
// `String.prototype.search` returns a number, so exclude chained accesses
77+
not exists(PropAccess p | p.getBase() = mce)
78+
)
7379
)
7480
}
7581

javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@
1010
| RegExpInjection.js:45:20:45:24 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
1111
| RegExpInjection.js:46:23:46:27 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
1212
| RegExpInjection.js:47:22:47:26 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
13+
| RegExpInjection.js:50:46:50:50 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
1314
| tst.js:3:16:3:35 | "^"+ data.name + "$" | This regular expression is constructed from a $@. | tst.js:1:46:1:46 | e | user-provided value |

javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
var express = require('express');
22
var app = express();
3-
3+
var URI = reuires("urijs");
44
app.get('/findKey', function(req, res) {
55
var key = req.param("key"), input = req.param("input");
66

@@ -46,4 +46,8 @@ app.get('/findKey', function(req, res) {
4646
likelyString.search(input); // NOT OK
4747
maybeString.search(input); // NOT OK
4848
notString.search(input); // OK
49+
50+
URI(`${protocol}://${host}${path}`).search(input); // OK, but still flagged
51+
URI(`${protocol}://${host}${path}`).search(input).href(); // OK
52+
unknown.search(input).unknown; // OK
4953
});

0 commit comments

Comments
 (0)