Skip to content

Commit 2a808b2

Browse files
committed
track taint through string coercions for js/prototype-polluting-assignment
1 parent 2d65aa1 commit 2a808b2

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,13 @@ class Configuration extends TaintTracking::Configuration {
3131
node instanceof Sanitizer
3232
or
3333
// Concatenating with a string will in practice prevent the string `__proto__` from arising.
34-
node instanceof StringOps::ConcatenationRoot
34+
exists(StringOps::ConcatenationRoot root | node = root |
35+
// Exclude the string coercion `"" + node` from this filter.
36+
not (
37+
strictcount(root.getALeaf()) = 2 and
38+
root.getALeaf().getStringValue() = ""
39+
)
40+
)
3541
}
3642

3743
override predicate isAdditionalFlowStep(

javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ nodes
5656
| tst.js:45:9:45:11 | obj |
5757
| tst.js:48:9:48:11 | obj |
5858
| tst.js:48:9:48:11 | obj |
59+
| tst.js:77:9:77:38 | taint |
60+
| tst.js:77:17:77:38 | String( ... y.data) |
61+
| tst.js:77:24:77:37 | req.query.data |
62+
| tst.js:77:24:77:37 | req.query.data |
63+
| tst.js:80:5:80:17 | object[taint] |
64+
| tst.js:80:5:80:17 | object[taint] |
65+
| tst.js:80:12:80:16 | taint |
66+
| tst.js:82:5:82:22 | object["" + taint] |
67+
| tst.js:82:5:82:22 | object["" + taint] |
68+
| tst.js:82:12:82:21 | "" + taint |
69+
| tst.js:82:17:82:21 | taint |
5970
edges
6071
| lib.js:1:38:1:40 | obj | lib.js:6:7:6:9 | obj |
6172
| lib.js:1:38:1:40 | obj | lib.js:6:7:6:9 | obj |
@@ -113,6 +124,16 @@ edges
113124
| tst.js:33:23:33:25 | obj | tst.js:45:9:45:11 | obj |
114125
| tst.js:33:23:33:25 | obj | tst.js:48:9:48:11 | obj |
115126
| tst.js:33:23:33:25 | obj | tst.js:48:9:48:11 | obj |
127+
| tst.js:77:9:77:38 | taint | tst.js:80:12:80:16 | taint |
128+
| tst.js:77:9:77:38 | taint | tst.js:82:17:82:21 | taint |
129+
| tst.js:77:17:77:38 | String( ... y.data) | tst.js:77:9:77:38 | taint |
130+
| tst.js:77:24:77:37 | req.query.data | tst.js:77:17:77:38 | String( ... y.data) |
131+
| tst.js:77:24:77:37 | req.query.data | tst.js:77:17:77:38 | String( ... y.data) |
132+
| tst.js:80:12:80:16 | taint | tst.js:80:5:80:17 | object[taint] |
133+
| tst.js:80:12:80:16 | taint | tst.js:80:5:80:17 | object[taint] |
134+
| tst.js:82:12:82:21 | "" + taint | tst.js:82:5:82:22 | object["" + taint] |
135+
| tst.js:82:12:82:21 | "" + taint | tst.js:82:5:82:22 | object["" + taint] |
136+
| tst.js:82:17:82:21 | taint | tst.js:82:12:82:21 | "" + taint |
116137
#select
117138
| lib.js:6:7:6:9 | obj | lib.js:1:43:1:46 | path | lib.js:6:7:6:9 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:1:43:1:46 | path | here |
118139
| lib.js:15:3:15:14 | obj[path[0]] | lib.js:14:38:14:41 | path | lib.js:15:3:15:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:14:38:14:41 | path | here |
@@ -124,3 +145,5 @@ edges
124145
| tst.js:39:9:39:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:39:9:39:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here |
125146
| tst.js:45:9:45:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:45:9:45:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here |
126147
| tst.js:48:9:48:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:48:9:48:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here |
148+
| tst.js:80:5:80:17 | object[taint] | tst.js:77:24:77:37 | req.query.data | tst.js:80:5:80:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:77:24:77:37 | req.query.data | here |
149+
| tst.js:82:5:82:22 | object["" + taint] | tst.js:77:24:77:37 | req.query.data | tst.js:82:5:82:22 | object["" + taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:77:24:77:37 | req.query.data | here |

javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,14 @@ class Box {
7171
this.foo = 'bar'; // OK - 'this' won't refer to Object.prototype
7272
}
7373
}
74+
75+
76+
app.get('/', (req, res) => {
77+
let taint = String(req.query.data);
78+
79+
let object = {};
80+
object[taint][taint] = taint; // NOT OK
81+
82+
object["" + taint]["" + taint] = taint; // NOT OK
83+
});
84+

0 commit comments

Comments
 (0)