diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll index dec1fb62706..76317e2d8eb 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll @@ -20,125 +20,6 @@ private string getTokenFeature(DataFlow::Node endpoint, string featureName) { featureName = getASupportedFeatureName() } -/** - * This module provides functionality for getting a representation of the access path of nodes - * within the program. - * - * For example, it gives the `User.find` callee here: - * - * ```js - * const mongoose = require('mongoose'), - * User = mongoose.model('User', null); - * User.find({ 'isAdmin': true }) - * ``` - * the access path `mongoose member model instanceorreturn member find instanceorreturn`. - * - * This access path is based on the simplified access path that the untrusted data flowing to - * external API query associates to each of its sinks, with modifications to optionally include - * explicit structural information and to improve how well the path tokenizes. - */ -private module AccessPaths { - bindingset[str] - private predicate isNumericString(string str) { exists(str.toInt()) } - - /** - * Gets a parameter of `base` with name `name`, or a property named `name` of a destructuring parameter. - */ - private API::Node getNamedParameter(API::Node base, string name) { - exists(API::Node param | - param = base.getAParameter() and - not param = base.getReceiver() - | - result = param and - name = param.asSource().asExpr().(Parameter).getName() - or - param.asSource().asExpr() instanceof DestructuringPattern and - result = param.getMember(name) - ) - } - - /** - * A utility class that is equivalent to `boolean` but does not require type joining. - */ - class Boolean extends boolean { - Boolean() { this = true or this = false } - } - - /** Get the access path for the node. This includes structural information like `member`, `param`, and `functionalarg` if `includeStructuralInfo` is true. */ - predicate accessPaths( - API::Node node, Boolean includeStructuralInfo, string accessPath, string apiName - ) { - //node = API::moduleImport(result) - node = API::moduleImport(apiName) and - accessPath = apiName - or - exists(API::Node previousNode, string previousAccessPath | - previousNode.getDepth() < node.getDepth() and - accessPaths(previousNode, includeStructuralInfo, previousAccessPath, apiName) - | - // e.g. `new X`, `X()` - node = [previousNode.getInstance(), previousNode.getReturn()] and - if includeStructuralInfo = true - then accessPath = previousAccessPath + " instanceorreturn" - else accessPath = previousAccessPath - or - // e.g. `x.y`, `x[y]`, `const { y } = x`, where `y` is non-numeric and is known at analysis - // time. - exists(string member | - node = previousNode.getMember(member) and - not node = previousNode.getUnknownMember() and - not isNumericString(member) and - not (member = "default" and previousNode = API::moduleImport(_)) and - not member = "then" // use the 'promised' edges for .then callbacks - | - if includeStructuralInfo = true - then accessPath = previousAccessPath + " member " + member - else accessPath = previousAccessPath + " " + member - ) - or - // e.g. `x.y`, `x[y]`, `const { y } = x`, where `y` is numeric or not known at analysis time. - ( - node = previousNode.getUnknownMember() or - node = previousNode.getMember(any(string s | isNumericString(s))) - ) and - if includeStructuralInfo = true - then accessPath = previousAccessPath + " member" - else accessPath = previousAccessPath - or - // e.g. `x.then(y => ...)` - node = previousNode.getPromised() and - accessPath = previousAccessPath - or - // e.g. `x.y((a, b) => ...)` - // Name callback parameters after their name in the source code. - // For example, the `res` parameter in `express.get('/foo', (req, res) => {...})` will be - // named `express member get functionalarg param res`. - exists(string paramName | - node = getNamedParameter(previousNode.getAParameter(), paramName) and - ( - if includeStructuralInfo = true - then accessPath = previousAccessPath + " functionalarg param " + paramName - else accessPath = previousAccessPath + " " + paramName - ) - or - exists(string callbackName, int index | - node = - getNamedParameter(previousNode - .getASuccessor(API::Label::parameter(index)) - .getMember(callbackName), paramName) and - index != -1 and // ignore receiver - if includeStructuralInfo = true - then - accessPath = - previousAccessPath + " functionalarg " + index + " " + callbackName + " param " + - paramName - else accessPath = previousAccessPath + " " + index + " " + callbackName + " " + paramName - ) - ) - ) - } -} - private module FunctionNames { /** * Get the name of the function.