Skip to content

Commit 9bd3c4a

Browse files
asger-semmleasgerf
authored andcommitted
JS: Add sanitizer for "in" exprs
1 parent 7ac30e2 commit 9bd3c4a

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ class PropNameTracking extends DataFlow::Configuration {
286286
node instanceof BlacklistEqualityGuard or
287287
node instanceof WhitelistEqualityGuard or
288288
node instanceof HasOwnPropertyGuard or
289+
node instanceof InExprGuard or
289290
node instanceof InstanceOfGuard or
290291
node instanceof TypeofGuard or
291292
node instanceof BlacklistInclusionGuard or
@@ -353,6 +354,25 @@ class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode, CallNode {
353354
}
354355
}
355356

357+
/**
358+
* Sanitizer guard for `key in dst`.
359+
*
360+
* Since `"__proto__" in obj` and `"constructor" in obj` is true for most objects,
361+
* this is seen as a sanitizer for `key` in the false outcome.
362+
*/
363+
class InExprGuard extends DataFlow::BarrierGuardNode, DataFlow::ValueNode {
364+
override InExpr astNode;
365+
366+
InExprGuard() {
367+
// Exclude tests of form `key in src` for the same reason as in HasOwnPropertyGuard
368+
not arePropertiesEnumerated(astNode.getRightOperand().flow().getALocalSource())
369+
}
370+
371+
override predicate blocks(boolean outcome, Expr e) {
372+
e = astNode.getLeftOperand() and outcome = false
373+
}
374+
}
375+
356376
/**
357377
* Sanitizer guard for `instanceof` expressions.
358378
*

javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,23 @@ nodes
815815
| PrototypePollutionUtility/tests.js:322:28:322:32 | value |
816816
| PrototypePollutionUtility/tests.js:322:28:322:32 | value |
817817
| PrototypePollutionUtility/tests.js:322:28:322:32 | value |
818+
| PrototypePollutionUtility/tests.js:328:30:328:32 | src |
819+
| PrototypePollutionUtility/tests.js:328:30:328:32 | src |
820+
| PrototypePollutionUtility/tests.js:336:42:336:44 | src |
821+
| PrototypePollutionUtility/tests.js:336:42:336:44 | src |
822+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] |
823+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] |
824+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] |
825+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] |
826+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] |
827+
| PrototypePollutionUtility/tests.js:338:28:338:30 | src |
828+
| PrototypePollutionUtility/tests.js:338:28:338:30 | src |
829+
| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
830+
| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
831+
| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
832+
| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
833+
| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
834+
| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
818835
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst |
819836
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst |
820837
| examples/PrototypePollutionUtility.js:1:21:1:23 | src |
@@ -1950,6 +1967,23 @@ edges
19501967
| PrototypePollutionUtility/tests.js:320:42:320:44 | key | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] |
19511968
| PrototypePollutionUtility/tests.js:320:48:320:52 | value | PrototypePollutionUtility/tests.js:314:36:314:38 | src |
19521969
| PrototypePollutionUtility/tests.js:320:48:320:52 | value | PrototypePollutionUtility/tests.js:314:36:314:38 | src |
1970+
| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:336:42:336:44 | src |
1971+
| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:336:42:336:44 | src |
1972+
| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:338:28:338:30 | src |
1973+
| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:338:28:338:30 | src |
1974+
| PrototypePollutionUtility/tests.js:336:42:336:44 | src | PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] |
1975+
| PrototypePollutionUtility/tests.js:336:42:336:44 | src | PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] |
1976+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src |
1977+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src |
1978+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src |
1979+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src |
1980+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src |
1981+
| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src |
1982+
| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
1983+
| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
1984+
| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
1985+
| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
1986+
| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] |
19531987
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst |
19541988
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst |
19551989
| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst |

javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,3 +324,19 @@ function mergeRephinementNode(dst, src) {
324324
}
325325
}
326326
}
327+
328+
function mergeSelective(dst, src) {
329+
for (let key in src) {
330+
if (src.hasOwnProperty(key)) {
331+
// Only 'prefs' is merged recursively
332+
if (key in dst && key !== 'prefs') {
333+
continue;
334+
}
335+
if (dst[key]) {
336+
mergeSelective(dst[key], src[key]);
337+
} else {
338+
dst[key] = src[key]; // OK
339+
}
340+
}
341+
}
342+
}

0 commit comments

Comments
 (0)