Skip to content

Commit 149ae5d

Browse files
author
Max Schaefer
committed
JavaScript: Fix IllegalInvocation.
This fixes false positives that arise when a call such as `f.apply` can either be interpreted as a reflective invocation of `f`, or a normal call to method `apply` of `f`.
1 parent 4780952 commit 149ae5d

File tree

5 files changed

+21
-1
lines changed

5 files changed

+21
-1
lines changed

change-notes/1.23/analysis-javascript.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
| Client-side cross-site scripting (`js/xss`) | More results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized. |
2626
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving functions that manipulate DOM event handler attributes are now recognized. |
2727
| Hard-coded credentials (`js/hardcoded-credentials`) | Fewer false-positive results | This rule now flags fewer password examples. |
28+
| Illegal invocation (`js/illegal-invocation`) | Fewer false-positive results | This rule now correctly handles methods named `call` and `apply`. |
2829
| Incorrect suffix check (`js/incorrect-suffix-check`) | Fewer false-positive results | The query recognizes valid checks in more cases.
2930
| Network data written to file (`js/http-to-file-access`) | Fewer false-positive results | This query has been renamed to better match its intended purpose, and now only considers network data untrusted. |
3031
| Password in configuration file (`js/password-in-configuration-file`) | Fewer false-positive results | This rule now flags fewer password examples. |

javascript/ql/src/LanguageFeatures/IllegalInvocation.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ where
5858
// filter out some easy cases
5959
not isCallToFunction(cs) and
6060
// conservatively only flag call sites where _all_ callees are illegal
61-
forex(Function otherCallee | otherCallee = cs.getACallee() |
61+
forex(DataFlow::InvokeNode cs2, Function otherCallee |
62+
cs2.getInvokeExpr() = cs.getInvokeExpr() and otherCallee = cs2.getACallee() |
6263
illegalInvocation(cs, otherCallee, _, _)
6364
)
6465
select cs, "Illegal invocation of $@ " + how + ".", callee, calleeDesc

javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,9 @@ module DataFlow {
935935
* and either with or without `new`.
936936
*/
937937
abstract class InvokeNodeDef extends DataFlow::Node {
938+
/** Gets the syntactic invoke expression underlying this function invocation. */
939+
abstract InvokeExpr getInvokeExpr();
940+
938941
/** Gets the name of the function or method being invoked, if it can be determined. */
939942
abstract string getCalleeName();
940943

@@ -985,6 +988,8 @@ module DataFlow {
985988
class ExplicitInvokeNode extends InvokeNodeDef, DataFlow::ValueNode {
986989
override InvokeExpr astNode;
987990

991+
override InvokeExpr getInvokeExpr() { result = astNode }
992+
988993
override string getCalleeName() { result = astNode.getCalleeName() }
989994

990995
override DataFlow::Node getCalleeNode() { result = DataFlow::valueNode(astNode.getCallee()) }
@@ -1046,6 +1051,8 @@ module DataFlow {
10461051

10471052
ReflectiveCallNodeDef() { this = TReflectiveCallNode(originalCall.asExpr(), kind) }
10481053

1054+
override InvokeExpr getInvokeExpr() { result = originalCall.getInvokeExpr() }
1055+
10491056
override string getCalleeName() {
10501057
result = originalCall.getReceiver().asExpr().(PropAccess).getPropertyName()
10511058
}

javascript/ql/src/semmle/javascript/dataflow/Nodes.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ class InvokeNode extends DataFlow::SourceNode {
3434

3535
InvokeNode() { this = impl }
3636

37+
/** Gets the syntactic invoke expression underlying this function invocation. */
38+
InvokeExpr getInvokeExpr() { result = impl.getInvokeExpr() }
39+
3740
/** Gets the name of the function or method being invoked, if it can be determined. */
3841
string getCalleeName() { result = impl.getCalleeName() }
3942

javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,12 @@ new h() // NOT OK
4545
C.call(); // NOT OK
4646
C.apply(); // NOT OK
4747

48+
class E {
49+
static call() {}
50+
static apply() {}
51+
}
52+
53+
E.call(); // OK
54+
E.apply(); // OK
55+
4856
//semmle-extractor-options: --experimental

0 commit comments

Comments
 (0)