Skip to content

Commit 2187b0c

Browse files
author
Max Schaefer
authored
Merge pull request #89 from esben-semmle/js/sharpen-type-confusion
JS: remove emptiness checks from the type confusion `x.length` sinks
2 parents 1aa7a2c + b4c77b8 commit 2187b0c

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

change-notes/1.18/analysis-javascript.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
| Reflected cross-site scripting | Fewer false-positive results | This rule now treats header names case-insensitively. |
107107
| Server-side URL redirect | More true-positive results | This rule now treats header names case-insensitively. |
108108
| Superfluous trailing arguments | Fewer false-positive results | This rule now ignores calls to some empty functions. |
109+
| Type confusion through parameter tampering | Fewer false-positive results | This rule no longer flags emptiness checks. |
109110
| Uncontrolled command line | More true-positive results | This rule now recognizes indirect command injection through `sh -c` and similar. |
110111
| Unused variable | Fewer results | This rule no longer flags class expressions that could be made anonymous. While technically true, these results are not interesting. |
111112
| Unused variable | Renamed | This rule has been renamed to "Unused variable, import, function or class" to reflect the fact that it flags different kinds of unused program elements. |

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,22 @@ module TypeConfusionThroughParameterTampering {
101101

102102
LengthAccess() {
103103
exists (DataFlow::PropRead read |
104-
read.accesses(this, "length")
104+
read.accesses(this, "length") and
105+
// exclude truthiness checks on the length: an array/string confusion cannot control an emptiness check
106+
not (
107+
exists (ConditionGuardNode cond |
108+
read.asExpr() = cond.getTest()
109+
)
110+
or
111+
exists (Comparison cmp, Expr zero |
112+
zero.getIntValue() = 0 and
113+
cmp.hasOperands(read.asExpr(), zero)
114+
)
115+
or
116+
exists (LogNotExpr neg |
117+
neg.getOperand() = read.asExpr()
118+
)
119+
)
105120
)
106121
}
107122

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,22 @@ express().get('/some/path/:foo', function(req, res) {
5050
var foo = req.params.foo;
5151
foo.indexOf(); // OK
5252
});
53+
54+
express().get('/some/path/:foo', function(req, res) {
55+
if (req.query.path.length) {} // OK
56+
req.query.path.length == 0; // OK
57+
!req.query.path.length; // OK
58+
req.query.path.length > 0; // OK
59+
});
60+
61+
express().get('/some/path/:foo', function(req, res) {
62+
let p = req.query.path;
63+
64+
if (typeof p !== 'string') {
65+
return;
66+
}
67+
68+
while (p.length) { // OK
69+
p = p.substr(1);
70+
}
71+
});

0 commit comments

Comments
 (0)