diff --git a/javascript/ql/src/semmle/javascript/frameworks/UriLibraries.qll b/javascript/ql/src/semmle/javascript/frameworks/UriLibraries.qll index f02dabbeea6..a18a43a308b 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/UriLibraries.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/UriLibraries.qll @@ -401,4 +401,33 @@ private module ClosureLibraryUri { succ = uri } } + + /** + * Provides classes for working with [path](https://nodejs.org/api/path.html) code. + */ + module path { + /** + * A taint step in the path module. + */ + private class Step extends UriLibraryStep, DataFlow::CallNode { + DataFlow::Node src; + + Step() { + exists(DataFlow::SourceNode ref | + ref = NodeJSLib::Path::moduleMember("parse") or + // a ponyfill: https://www.npmjs.com/package/path-parse + ref = DataFlow::moduleImport("path-parse") or + ref = DataFlow::moduleMember("path-parse", "posix") or + ref = DataFlow::moduleMember("path-parse", "win32") + | + this = ref.getACall() and + src = getAnArgument() + ) + } + + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + pred = src and succ = this + } + } + } } diff --git a/javascript/ql/test/library-tests/frameworks/UriLibraries/UriLibraryStep.expected b/javascript/ql/test/library-tests/frameworks/UriLibraries/UriLibraryStep.expected index 14e4925237d..df849dea08a 100644 --- a/javascript/ql/test/library-tests/frameworks/UriLibraries/UriLibraryStep.expected +++ b/javascript/ql/test/library-tests/frameworks/UriLibraries/UriLibraryStep.expected @@ -24,6 +24,12 @@ | closureUri.js:23:1:23:18 | utils.getPath(uri) | closureUri.js:23:15:23:17 | uri | closureUri.js:23:1:23:18 | utils.getPath(uri) | | closureUri.js:27:1:27:23 | stringU ... code(x) | closureUri.js:27:22:27:22 | x | closureUri.js:27:1:27:23 | stringU ... code(x) | | closureUri.js:28:1:28:23 | stringU ... code(x) | closureUri.js:28:22:28:22 | x | closureUri.js:28:1:28:23 | stringU ... code(x) | +| path-parse.js:4:1:4:13 | path.parse(x) | path-parse.js:4:12:4:12 | x | path-parse.js:4:1:4:13 | path.parse(x) | +| path-parse.js:5:1:5:13 | path_parse(x) | path-parse.js:5:12:5:12 | x | path-parse.js:5:1:5:13 | path_parse(x) | +| path-parse.js:6:1:6:19 | path.posix.parse(x) | path-parse.js:6:18:6:18 | x | path-parse.js:6:1:6:19 | path.posix.parse(x) | +| path-parse.js:7:1:7:19 | path_parse.posix(x) | path-parse.js:7:18:7:18 | x | path-parse.js:7:1:7:19 | path_parse.posix(x) | +| path-parse.js:8:1:8:19 | path.win32.parse(x) | path-parse.js:8:18:8:18 | x | path-parse.js:8:1:8:19 | path.win32.parse(x) | +| path-parse.js:9:1:9:19 | path_parse.win32(x) | path-parse.js:9:18:9:18 | x | path-parse.js:9:1:9:19 | path_parse.win32(x) | | punycode.js:3:9:3:26 | punycode.decode(x) | punycode.js:3:25:3:25 | x | punycode.js:3:9:3:26 | punycode.decode(x) | | punycode.js:5:5:5:22 | punycode.encode(x) | punycode.js:5:21:5:21 | x | punycode.js:5:5:5:22 | punycode.encode(x) | | punycode.js:7:5:7:25 | punycod ... code(x) | punycode.js:7:24:7:24 | x | punycode.js:7:5:7:25 | punycod ... code(x) | diff --git a/javascript/ql/test/library-tests/frameworks/UriLibraries/path-parse.js b/javascript/ql/test/library-tests/frameworks/UriLibraries/path-parse.js new file mode 100644 index 00000000000..293aaa7c57a --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/UriLibraries/path-parse.js @@ -0,0 +1,9 @@ +const path = require('path'); +const path_parse = require('path-parse'); + +path.parse(x); +path_parse(x); +path.posix.parse(x); +path_parse.posix(x); +path.win32.parse(x); +path_parse.win32(x);