Data flow cheat sheet ===================== This page describes parts of the JavaScript QL libraries commonly used for variant analysis and in data flow queries. Taint tracking path queries --------------------------- Use the following template to create a taint tracking path query: .. code-block:: ql /** * @kind path-problem */ import javascript import DataFlow import DataFlow::PathGraph class MyConfig extends TaintTracking::Configuration { MyConfig() { this = "MyConfig" } override predicate isSource(Node node) { ... } override predicate isSink(Node node) { ... } override predicate isAdditionalTaintStep(Node pred, Node succ) { ... } } from MyConfig cfg, PathNode source, PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, "taint from $@.", source.getNode(), "here" This query reports flow paths which: - Begin at a node matched by `isSource `__. - Step through variables, function calls, properties, strings, arrays, promises, exceptions, and steps added by `isAdditionalTaintStep `__. - End at a node matched by `isSink `__. See also: `Global data flow `__ and :doc:`Constructing path queries <../writing-queries/path-queries>`. DataFlow module --------------- Use data flow nodes to match program elements independently of syntax. See also: :doc:`Analyzing data flow in JavaScript/TypeScript `. Predicates in the ``DataFlow::`` module: - `moduleImport `__ -- finds uses of a module - `moduleMember `__ -- finds uses of a module member - `globalVarRef `__ -- finds uses of a global variable Classes and member predicates in the ``DataFlow::`` module: - `Node `__ -- something that can have a value, such as an expression, declaration, or SSA variable - `getALocalSource `__ -- find the node that this came from - `getTopLevel `__ -- top-level scope enclosing this node - `getFile `__ -- file containing this node - `getIntValue `__ -- value of this node if it's is an integer constant - `getStringValue `__ -- value of this node if it's is a string constant - `mayHaveBooleanValue `__ -- check if the value is ``true`` or ``false`` - `SourceNode `__ extends `Node `__ -- function call, parameter, object creation, or reference to a property or global variable - `getACall `__ -- find calls with this as the callee - `getAnInstantiation `__ -- find ``new``-calls with this as the callee - `getAnInvocation `__ -- find calls or ``new``-calls with this as the callee - `getAMethodCall `__ -- find method calls with this as the receiver - `getAMemberCall `__ -- find calls with a member of this as the receiver - `getAPropertyRead `__ -- find property reads with this as the base - `getAPropertyWrite `__ -- find property writes with this as the base - `getAPropertySource `__ -- find nodes flowing into a property of this node - `InvokeNode `__, `NewNode `__, `CallNode `__, `MethodCallNode `__ extends `SourceNode `__ -- call to a function or constructor - `getArgument `__ -- an argument to the call - `getCalleeNode `__ -- node being invoked as a function - `getCalleeName `__ -- name of the variable or property being called - `getOptionArgument `__ -- a "named argument" passed in through an object literal - `getCallback `__ -- a function passed as a callback - `getACallee `__ - a function being called here - (MethodCallNode).\ `getMethodName `__ -- name of the method being invoked - (MethodCallNode).\ `getReceiver `__ -- receiver of the method call - `FunctionNode `__ extends `SourceNode `__ -- definition of a function, including closures, methods, and class constructors - `getName `__ -- name of the function, derived from a variable or property name - `getParameter `__ -- a parameter of the function - `getReceiver `__ -- the node representing the value of ``this`` - `getAReturn `__ -- get a returned expression - `ParameterNode `__ extends `SourceNode `__ -- parameter of a function - `getName `__ -- the parameter name, if it has one - `ClassNode `__ extends `SourceNode `__ -- class declaration or function that acts as a class - `getName `__ -- name of the class, derived from a variable or property name - `getConstructor `__ -- the constructor function - `getInstanceMethod `__ -- get an instance method by name - `getStaticMethod `__ -- get a static method by name - `getAnInstanceReference `__ -- find references to an instance of the class - `getAClassReference `__ -- find references to the class itself - `ObjectLiteralNode `__ extends `SourceNode `__ -- object literal - `getAPropertyWrite `__ -- a property in the object literal - `getAPropertySource `__ -- value flowing into a property - `ArrayCreationNode `__ extends `SourceNode `__ -- array literal or call to ``Array`` constructor - `getElement `__ -- an element of the array - `PropRef `__, `PropRead `__, `PropWrite `__ -- read or write of a property - `getPropertyName `__ -- name of the property, if it is constant - `getPropertyNameExpr `__ -- expression holding the name of the property - `getBase `__ -- object whose property is accessed - (PropWrite).\ `getRhs `__ -- right-hand side of the property assignment StringOps module ---------------- - StringOps::`Concatenation `__ -- string concatenation, using a plus operator, template literal, or array join call - StringOps::`StartsWith `__ -- check if a string starts with something - StringOps::`EndsWith `__ -- check if a string ends with something - StringOps::`Includes `__ -- check if a string contains something Utility -------- - `ExtendCall `__ -- call that copies properties from one object to another - `JsonParserCall `__ -- call that deserializes a JSON string - `PropertyProjection `__ -- call that extracts nested properties by name System and Network ------------------ - `ClientRequest `__ -- outgoing network request - `DatabaseAccess `__ -- query being submitted to a database - `FileNameSource `__ -- reference to a filename - `FileSystemAccess `__ -- file system operation - `FileSystemReadAccess `__ -- reading the contents of a file - `FileSystemWriteAccess `__ -- writing to the contents of a file - `PersistentReadAccess `__ -- reading from persistent storage, like cookies - `PersistentWriteAccess `__ -- writing to persistent storage - `RemoteFlowSource `__ -- source of untrusted user input - `SystemCommandExecution `__ -- execution of a system command Files ----- - `File `__, `Folder `__ extends `Container `__ -- file or folder in the snapshot - `getBaseName `__ -- the name of the file or folder - `getRelativePath `__ -- path relative to the snapshot root AST nodes --------- See also: :doc:`AST class reference `. Conversion between DataFlow and AST nodes: - `Node.asExpr() `__ -- convert node to an expression, if possible - `Expr.flow() `__ -- convert expression to a node (always possible) - `DataFlow::valueNode `__ -- convert expression or declaration to a node - `DataFlow::parameterNode `__ -- convert a parameter to a node - `DataFlow::thisNode `__ -- get the receiver node of a function String matching --------------- - x.\ `matches `__\ ("escape%") -- holds if x starts with "escape" - x.\ `regexpMatch `__\ ("escape.*") -- holds if x starts with "escape" - x.\ `regexpMatch `__\ ("(?i).*escape.*") -- holds if x contains "escape" (case insensitive) Type tracking ------------- See also: :doc:`Type tracking tutorial `. Use the following template to define forward type tracking predicates: .. code-block:: ql import DataFlow SourceNode myType(TypeTracker t) { t.start() and result = /* SourceNode to track */ or exists(TypeTracker t2 | result = myType(t2).track(t2, t) ) } SourceNode myType() { result = myType(TypeTracker::end()) } Use the following template to define backward type tracking predicates: .. code-block:: ql import DataFlow SourceNode myType(TypeBackTracker t) { t.start() and result = (/* argument to track */).getALocalSource() or exists(TypeBackTracker t2 | result = myType(t2).backtrack(t2, t) ) } SourceNode myType() { result = myType(TypeBackTracker::end()) } Troubleshooting --------------- - Using a call node as as sink? Try using `getArgument `__ to get an *argument* of the call node instead. - Trying to use `moduleImport `__ or `moduleMember `__ as a call node? Try using `getACall `__ to get a *call* to the imported function, instead of the function itself. - Compilation fails due to incompatible types? Make sure AST nodes and DataFlow nodes are not mixed up. Use `asExpr() `__ or `flow() `__ to convert.