diff --git a/javascript/ql/lib/change-notes/2025-06-20-sinon.md b/javascript/ql/lib/change-notes/2025-06-20-sinon.md new file mode 100644 index 000000000000..fd8b8e0ad079 --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-06-20-sinon.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Calls to `sinon.match()` are no longer incorrectly identified as regular expression operations. diff --git a/javascript/ql/lib/semmle/javascript/Regexp.qll b/javascript/ql/lib/semmle/javascript/Regexp.qll index 642a3d196fb7..ea2993ae7da8 100644 --- a/javascript/ql/lib/semmle/javascript/Regexp.qll +++ b/javascript/ql/lib/semmle/javascript/Regexp.qll @@ -998,6 +998,8 @@ private predicate isUsedAsNonMatchObject(DataFlow::MethodCallNode call) { or // Result is obviously unused call.asExpr() = any(ExprStmt stmt).getExpr() + or + call = API::moduleImport("sinon").getMember("match").getACall() ) } diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp/tst-IncompleteHostnameRegExp.js b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp/tst-IncompleteHostnameRegExp.js index ae0447f132fd..b2e030a54921 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp/tst-IncompleteHostnameRegExp.js +++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp/tst-IncompleteHostnameRegExp.js @@ -60,4 +60,8 @@ /^(foo.example\.com|whatever)$/; // $ Alert (but kinda OK - one disjunction doesn't even look like a hostname) if (s.matchAll("^http://test.example.com")) {} // $ Alert + + const sinon = require('sinon'); + const megacliteUrl = "https://a.b.com"; + sinon.assert.calledWith(postStub.firstCall, sinon.match(megacliteUrl)); }); diff --git a/javascript/ql/test/query-tests/Security/CWE-020/MissingRegExpAnchor/tst.js b/javascript/ql/test/query-tests/Security/CWE-020/MissingRegExpAnchor/tst.js new file mode 100644 index 000000000000..d4e4d97b651e --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-020/MissingRegExpAnchor/tst.js @@ -0,0 +1,6 @@ +const sinon = require('sinon'); + +function testFunction() { + const megacliteUrl = "https://a.b.com"; + sinon.assert.calledWith(postStub.firstCall, sinon.match(megacliteUrl)); +}