Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 279c584

Browse files
committed
fix FP in js/path-injection by recognizing more prefix checks
1 parent f8d0b4e commit 279c584

5 files changed

Lines changed: 19 additions & 15 deletions

File tree

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

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,13 @@ abstract class EnumeratedPropName extends DataFlow::Node {
4747
*/
4848
abstract DataFlow::Node getSourceObject();
4949

50-
/**
51-
* Gets a local reference of the source object.
52-
*/
53-
SourceNode getASourceObjectRef() {
54-
exists(SourceNode root, string path |
55-
getSourceObject() = AccessPath::getAReferenceTo(root, path) and
56-
result = AccessPath::getAReferenceTo(root, path)
57-
)
58-
or
59-
result = getSourceObject().getALocalSource()
60-
}
61-
6250
/**
6351
* Gets a property read that accesses the corresponding property value in the source object.
6452
*
6553
* For example, gets `src[key]` in `for (var key in src) { src[key]; }`.
6654
*/
6755
PropRead getASourceProp() {
68-
result = getASourceObjectRef().getAPropertyRead() and
56+
result = AccessPath::getASourceAccess(getSourceObject()).getAPropertyRead() and
6957
result.getPropertyNameExpr().flow().getImmediatePredecessor*() = this
7058
}
7159
}

javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,4 +412,16 @@ module AccessPath {
412412
isAssignedInUniqueFile(name)
413413
)
414414
}
415+
416+
/**
417+
* Gets a SourceNode that is accessed using the same access path as the input.
418+
*/
419+
DataFlow::SourceNode getASourceAccess(DataFlow::Node node) {
420+
exists(DataFlow::SourceNode root, string accessPath |
421+
node = AccessPath::getAReferenceTo(root, accessPath) and
422+
result = AccessPath::getAReferenceTo(root, accessPath)
423+
)
424+
or
425+
result = node.getALocalSource()
426+
}
415427
}

javascript/ql/src/semmle/javascript/StringOps.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,10 @@ module StringOps {
165165

166166
StartsWith_Substring() {
167167
astNode.hasOperands(call.asExpr(), substring.asExpr()) and
168-
(call.getMethodName() = "substring" or call.getMethodName() = "substr") and
168+
(call.getMethodName() = "substring" or call.getMethodName() = "substr" or call.getMethodName() = "slice") and
169169
call.getNumArgument() = 2 and
170170
(
171-
substring.getALocalSource().getAPropertyRead("length").flowsTo(call.getArgument(1))
171+
AccessPath::getASourceAccess(substring).getAPropertyRead("length").flowsTo(call.getArgument(1))
172172
or
173173
substring.getStringValue().length() = call.getArgument(1).asExpr().getIntValue()
174174
)

javascript/ql/test/library-tests/StringOps/StartsWith/StartsWith.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@
1414
| tst.js:19:9:19:36 | A.subst ... "web/" | tst.js:19:9:19:9 | A | tst.js:19:31:19:36 | "web/" | true |
1515
| tst.js:32:9:32:32 | strings ... h(A, B) | tst.js:32:28:32:28 | A | tst.js:32:31:32:31 | B | true |
1616
| tst.js:33:9:33:47 | strings ... h(A, B) | tst.js:33:43:33:43 | A | tst.js:33:46:33:46 | B | true |
17+
| tst.js:34:9:34:34 | A.slice ... ) !== B | tst.js:34:9:34:9 | A | tst.js:34:34:34:34 | B | false |
18+
| tst.js:35:9:35:42 | A.slice ... = B.foo | tst.js:35:9:35:9 | A | tst.js:35:38:35:42 | B.foo | false |

javascript/ql/test/library-tests/StringOps/StartsWith/tst.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ function f(A, B) {
3131

3232
if (strings.startsWith(A, B)) {}
3333
if (strings.caseInsensitiveStartsWith(A, B)) {}
34+
if (A.slice(0, B.length) !== B) {}
35+
if (A.slice(0, B.foo.length) !== B.foo) {}
3436
}

0 commit comments

Comments
 (0)