From 2cbcc1d37abcac1e78a47ff74c28641e9dba77d9 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 29 Aug 2025 11:56:15 +0200 Subject: [PATCH 01/59] JS: Overlay annotations for AST layer --- .../ql/lib/Expressions/ExprHasNoEffect.qll | 6 ++ javascript/ql/lib/semmle/javascript/AMD.qll | 20 ++++-- javascript/ql/lib/semmle/javascript/AST.qll | 5 ++ javascript/ql/lib/semmle/javascript/CFG.qll | 2 + .../ql/lib/semmle/javascript/Classes.qll | 5 ++ .../ql/lib/semmle/javascript/Closure.qll | 23 +++++++ .../ql/lib/semmle/javascript/Comments.qll | 2 + .../ql/lib/semmle/javascript/Constants.qll | 2 + .../ql/lib/semmle/javascript/DefUse.qll | 4 ++ javascript/ql/lib/semmle/javascript/E4X.qll | 2 + .../lib/semmle/javascript/ES2015Modules.qll | 27 ++++++++ .../ql/lib/semmle/javascript/Errors.qll | 2 + javascript/ql/lib/semmle/javascript/Expr.qll | 37 +++++++++++ .../ql/lib/semmle/javascript/Externs.qll | 2 + javascript/ql/lib/semmle/javascript/Files.qll | 8 +++ .../ql/lib/semmle/javascript/Functions.qll | 4 ++ javascript/ql/lib/semmle/javascript/HTML.qll | 3 + javascript/ql/lib/semmle/javascript/JSDoc.qll | 3 + javascript/ql/lib/semmle/javascript/JSON.qll | 2 + javascript/ql/lib/semmle/javascript/JSX.qll | 2 + javascript/ql/lib/semmle/javascript/Lines.qll | 2 + .../ql/lib/semmle/javascript/Locations.qll | 2 + .../ql/lib/semmle/javascript/Modules.qll | 16 +++++ javascript/ql/lib/semmle/javascript/NPM.qll | 2 + .../ql/lib/semmle/javascript/NodeJS.qll | 15 +++++ .../ql/lib/semmle/javascript/Promises.qll | 2 + .../ql/lib/semmle/javascript/Regexp.qll | 16 +++++ javascript/ql/lib/semmle/javascript/SSA.qll | 2 + javascript/ql/lib/semmle/javascript/Stmt.qll | 2 + .../ql/lib/semmle/javascript/Templates.qll | 3 + .../ql/lib/semmle/javascript/Tokens.qll | 2 + .../lib/semmle/javascript/TypeAnnotations.qll | 9 +++ .../ql/lib/semmle/javascript/TypeScript.qll | 63 +++++++++++++++++++ .../ql/lib/semmle/javascript/Variables.qll | 8 +++ javascript/ql/lib/semmle/javascript/XML.qll | 2 + javascript/ql/lib/semmle/javascript/YAML.qll | 2 + .../javascript/dataflow/AbstractValues.qll | 3 + .../dataflow/AdditionalFlowSteps.qll | 5 ++ .../javascript/dataflow/Configuration.qll | 8 +++ .../CustomAbstractValueDefinitions.qll | 5 ++ .../semmle/javascript/dataflow/DataFlow.qll | 16 +++++ .../javascript/dataflow/FlowSummary.qll | 2 + .../javascript/dataflow/InferredTypes.qll | 3 + .../lib/semmle/javascript/dataflow/Nodes.qll | 24 ++++++- .../javascript/dataflow/Refinements.qll | 21 +++++++ .../semmle/javascript/dataflow/Sources.qll | 4 ++ .../dataflow/internal/AbstractValuesImpl.qll | 2 + .../dataflow/internal/AccessPaths.qll | 2 + .../internal/AdditionalFlowInternal.qll | 4 ++ .../javascript/dataflow/internal/Contents.qll | 9 +++ .../dataflow/internal/DataFlowNode.qll | 2 + .../dataflow/internal/DataFlowPrivate.qll | 52 +++++++++++++++ .../dataflow/internal/FlowSteps.qll | 25 ++++---- .../dataflow/internal/FlowSummaryPrivate.qll | 3 + .../dataflow/internal/VariableCapture.qll | 3 + .../dataflow/internal/VariableOrThis.qll | 3 + .../dataflow/internal/sharedlib/Ssa.qll | 2 + .../javascript/frameworks/LazyCache.qll | 3 + .../frameworks/LodashUnderscore.qll | 20 ++++++ .../javascript/frameworks/NodeJSLib.qll | 4 ++ .../javascript/frameworks/Templating.qll | 38 +++++++++++ .../javascript/frameworks/UriLibraries.qll | 2 + .../frameworks/data/ModelsAsData.qll | 2 + .../data/internal/ApiGraphModels.qll | 2 + .../internal/ApiGraphModelsExtensions.qll | 2 + .../data/internal/ApiGraphModelsSpecific.qll | 5 ++ .../internal/BasicBlockInternal.qll | 2 + .../javascript/internal/CachedStages.qll | 10 +-- .../javascript/internal/StmtContainers.qll | 2 + .../flow_summaries/AmbiguousCoreMethods.qll | 2 + .../internal/flow_summaries/Arrays.qll | 2 + .../internal/flow_summaries/AsyncAwait.qll | 2 + .../internal/flow_summaries/Decoders.qll | 3 + .../flow_summaries/DynamicImportStep.qll | 2 + .../internal/flow_summaries/ExceptionFlow.qll | 2 + .../flow_summaries/FlowSummaryUtil.qll | 3 + .../internal/flow_summaries/ForOfLoops.qll | 2 + .../internal/flow_summaries/Generators.qll | 2 + .../internal/flow_summaries/Iterators.qll | 2 + .../internal/flow_summaries/JsonStringify.qll | 2 + .../internal/flow_summaries/Maps.qll | 2 + .../internal/flow_summaries/Promises.qll | 2 + .../internal/flow_summaries/Sets.qll | 2 + .../internal/flow_summaries/Strings.qll | 2 + .../internal/flow_summaries/TypedArrays.qll | 3 + .../flow_summaries/UrlSearchParams.qll | 2 + 86 files changed, 615 insertions(+), 21 deletions(-) diff --git a/javascript/ql/lib/Expressions/ExprHasNoEffect.qll b/javascript/ql/lib/Expressions/ExprHasNoEffect.qll index 9813d9b32ed9..5e194b3fc3a5 100644 --- a/javascript/ql/lib/Expressions/ExprHasNoEffect.qll +++ b/javascript/ql/lib/Expressions/ExprHasNoEffect.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for the 'js/useless-expression' query. */ +overlay[local] +module; import javascript import DOMProperties @@ -60,6 +62,7 @@ predicate isDeclaration(Expr e) { /** * Holds if there exists a getter for a property called `name` anywhere in the program. */ +overlay[global] predicate isGetterProperty(string name) { // there is a call of the form `Object.defineProperty(..., name, descriptor)` ... exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() | @@ -85,6 +88,7 @@ predicate isGetterProperty(string name) { /** * A property access that may invoke a getter. */ +overlay[global] class GetterPropertyAccess extends PropAccess { override predicate isImpure() { isGetterProperty(this.getPropertyName()) } } @@ -123,6 +127,7 @@ predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) { * even if they do, the call itself is useless and should be flagged by this * query. */ +overlay[global] predicate noSideEffects(Expr e) { e.isPure() or @@ -148,6 +153,7 @@ predicate isCompoundExpression(Expr e) { /** * Holds if the expression `e` should be reported as having no effect. */ +overlay[global] predicate hasNoEffect(Expr e) { noSideEffects(e) and inVoidContext(e) and diff --git a/javascript/ql/lib/semmle/javascript/AMD.qll b/javascript/ql/lib/semmle/javascript/AMD.qll index 4828aff27cc4..e66a04ce4ecd 100644 --- a/javascript/ql/lib/semmle/javascript/AMD.qll +++ b/javascript/ql/lib/semmle/javascript/AMD.qll @@ -2,6 +2,8 @@ * Provides classes for working with * [Asynchronous Module Definitions](https://github.com/amdjs/amdjs-api/wiki/AMD). */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -62,9 +64,11 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range } /** DEPRECATED. Use `getDependencyExpr` instead. */ + overlay[global] deprecated PathExpr getDependency(int i) { result = this.getDependencyExpr(i) } /** DEPRECATED. Use `getADependencyExpr` instead. */ + overlay[global] deprecated PathExpr getADependency() { result = this.getADependencyExpr() } /** Gets the `i`th dependency of this module definition. */ @@ -194,16 +198,19 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range * Gets an abstract value representing one or more values that may flow * into this module's `module.exports` property. */ + overlay[global] DefiniteAbstractValue getAModuleExportsValue() { result = [this.getAnImplicitExportsValue(), this.getAnExplicitExportsValue()] } + overlay[global] pragma[noinline, nomagic] private AbstractValue getAnImplicitExportsValue() { // implicit exports: anything that is returned from the factory function result = this.getModuleExpr().analyze().getAValue() } + overlay[global] pragma[noinline] private AbstractValue getAnExplicitExportsValue() { // explicit exports: anything assigned to `module.exports` @@ -227,6 +234,7 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range private predicate isPseudoDependency(string s) { s = ["exports", "require", "module"] } /** An AMD dependency, considered as a path expression. */ +overlay[global] private class AmdDependencyPath extends PathExprCandidate { AmdDependencyPath() { exists(AmdModuleDefinition amd | @@ -239,6 +247,7 @@ private class AmdDependencyPath extends PathExprCandidate { } /** A constant path element appearing in an AMD dependency expression. */ +overlay[global] deprecated private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString { ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() } @@ -281,6 +290,7 @@ private class AmdDependencyImport extends Import { * Specifically, we look for files whose absolute path ends with the imported path, possibly * adding well-known JavaScript file extensions like `.js`. */ + overlay[global] private File guessTarget() { exists(FilePath imported, string abspath, string dirname, string basename | this.targetCandidate(result, abspath, imported, dirname, basename) @@ -303,6 +313,7 @@ private class AmdDependencyImport extends Import { * Additionally, `abspath` is bound to the absolute path of `f`, `imported` to the imported path, and * `dirname` and `basename` to the dirname and basename (respectively) of `imported`. */ + overlay[global] private predicate targetCandidate( File f, string abspath, FilePath imported, string dirname, string basename ) { @@ -316,10 +327,12 @@ private class AmdDependencyImport extends Import { /** * Gets the module whose absolute path matches this import, if there is only a single such module. */ + overlay[global] private Module resolveByAbsolutePath() { result.getFile() = unique(File file | file = this.guessTarget()) } + overlay[global] override Module getImportedModule() { result = super.getImportedModule() or @@ -348,14 +361,12 @@ private class AmdDependencyImport extends Import { */ class AmdModule extends Module { cached - AmdModule() { - Stages::DataFlowStage::ref() and - exists(unique(AmdModuleDefinition def | amdModuleTopLevel(def, this))) - } + AmdModule() { exists(unique(AmdModuleDefinition def | amdModuleTopLevel(def, this))) } /** Gets the definition of this module. */ AmdModuleDefinition getDefine() { amdModuleTopLevel(result, this) } + overlay[global] override DataFlow::Node getAnExportedValue(string name) { exists(DataFlow::PropWrite pwn | result = pwn.getRhs() | pwn.getBase().analyze().getAValue() = this.getDefine().getAModuleExportsValue() and @@ -363,6 +374,7 @@ class AmdModule extends Module { ) } + overlay[global] override DataFlow::Node getABulkExportedNode() { // Assigned to `module.exports` via the factory's `module` parameter exists(AbstractModuleObject m, DataFlow::PropWrite write | diff --git a/javascript/ql/lib/semmle/javascript/AST.qll b/javascript/ql/lib/semmle/javascript/AST.qll index db0a2e153d50..6a0d35abea50 100644 --- a/javascript/ql/lib/semmle/javascript/AST.qll +++ b/javascript/ql/lib/semmle/javascript/AST.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with the AST-based representation of JavaScript programs. */ +overlay[local] +module; import javascript private import internal.StmtContainers @@ -470,6 +472,7 @@ module AST { */ class ValueNode extends AstNode, @dataflownode { /** Gets type inference results for this element. */ + overlay[global] DataFlow::AnalyzedNode analyze() { result = DataFlow::valueNode(this).analyze() } /** Gets the data flow node associated with this program element. */ @@ -481,6 +484,7 @@ module AST { * This can be used to map an expression to the class it refers to, or * associate it with a named value coming from an dependency. */ + overlay[global] ExprNameBindingNode getNameBinding() { result = this } /** @@ -490,6 +494,7 @@ module AST { * (according to the type system), or to associate it with a named type coming * from a dependency. */ + overlay[global] TypeNameBindingNode getTypeBinding() { TypeResolution::valueHasType(this, result) } } } diff --git a/javascript/ql/lib/semmle/javascript/CFG.qll b/javascript/ql/lib/semmle/javascript/CFG.qll index 95e1e9aef72a..2270ddfeaaf3 100644 --- a/javascript/ql/lib/semmle/javascript/CFG.qll +++ b/javascript/ql/lib/semmle/javascript/CFG.qll @@ -272,6 +272,8 @@ * Note that the `import` statement as a whole is part of the CFG of the body, while its single * import specifier `x as y` forms part of the preamble. */ +overlay[local] +module; import javascript private import internal.StmtContainers diff --git a/javascript/ql/lib/semmle/javascript/Classes.qll b/javascript/ql/lib/semmle/javascript/Classes.qll index 394ab7910276..2485553370c6 100644 --- a/javascript/ql/lib/semmle/javascript/Classes.qll +++ b/javascript/ql/lib/semmle/javascript/Classes.qll @@ -4,6 +4,8 @@ * Class declarations and class expressions are modeled by (QL) classes `ClassDeclaration` * and `ClassExpression`, respectively, which are both subclasses of `ClassDefinition`. */ +overlay[local] +module; import javascript @@ -119,6 +121,7 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized { * * Anonymous classes and interfaces do not have a canonical name. */ + overlay[global] deprecated TypeName getTypeName() { result.getADefinition() = this } /** @@ -253,6 +256,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod /** * Gets the definition of the super class of this class, if it can be determined. */ + overlay[global] ClassDefinition getSuperClassDefinition() { result = this.getSuperClass().analyze().getAValue().(AbstractClass).getClass() } @@ -580,6 +584,7 @@ class MemberDeclaration extends @property, Documentable { int getMemberIndex() { properties(this, _, result, _, _) } /** Holds if the name of this member is computed by an impure expression. */ + overlay[global] predicate hasImpureNameExpr() { this.isComputed() and this.getNameExpr().isImpure() } /** diff --git a/javascript/ql/lib/semmle/javascript/Closure.qll b/javascript/ql/lib/semmle/javascript/Closure.qll index c31698333393..fd13023b2e6e 100644 --- a/javascript/ql/lib/semmle/javascript/Closure.qll +++ b/javascript/ql/lib/semmle/javascript/Closure.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with the Closure-Library module system. */ +overlay[local] +module; import javascript @@ -40,6 +42,7 @@ module Closure { /** * A reference to a Closure namespace. */ + overlay[global] deprecated class ClosureNamespaceRef extends DataFlow::Node instanceof ClosureNamespaceRef::Range { /** * Gets the namespace being referenced. @@ -47,6 +50,7 @@ module Closure { string getClosureNamespace() { result = super.getClosureNamespace() } } + overlay[global] deprecated module ClosureNamespaceRef { /** * A reference to a Closure namespace. @@ -64,9 +68,11 @@ module Closure { /** * A data flow node that returns the value of a closure namespace. */ + overlay[global] deprecated class ClosureNamespaceAccess extends ClosureNamespaceRef instanceof ClosureNamespaceAccess::Range { } + overlay[global] deprecated module ClosureNamespaceAccess { /** * A data flow node that returns the value of a closure namespace. @@ -79,6 +85,7 @@ module Closure { /** * A call to a method on the `goog.` namespace, as a closure reference. */ + overlay[global] abstract deprecated private class DefaultNamespaceRef extends DataFlow::MethodCallNode, ClosureNamespaceRef::Range { @@ -91,6 +98,7 @@ module Closure { * Holds if `node` is the data flow node corresponding to the expression in * a top-level expression statement. */ + overlay[global] deprecated private predicate isTopLevelExpr(DataFlow::Node node) { any(TopLevel tl).getAChildStmt().(ExprStmt).getExpr().flow() = node } @@ -98,6 +106,7 @@ module Closure { /** * A top-level call to `goog.provide`. */ + overlay[global] deprecated private class DefaultClosureProvideCall extends DefaultNamespaceRef { DefaultClosureProvideCall() { this.getMethodName() = "provide" and @@ -108,12 +117,14 @@ module Closure { /** * A top-level call to `goog.provide`. */ + overlay[global] deprecated class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureProvideCall { } /** * A call to `goog.require`. */ + overlay[global] deprecated private class DefaultClosureRequireCall extends DefaultNamespaceRef, ClosureNamespaceAccess::Range { @@ -123,12 +134,14 @@ module Closure { /** * A call to `goog.require`. */ + overlay[global] deprecated class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode instanceof DefaultClosureRequireCall { } /** * A top-level call to `goog.module` or `goog.declareModuleId`. */ + overlay[global] deprecated private class DefaultClosureModuleDeclaration extends DefaultNamespaceRef { DefaultClosureModuleDeclaration() { (this.getMethodName() = "module" or this.getMethodName() = "declareModuleId") and @@ -139,6 +152,7 @@ module Closure { /** * A top-level call to `goog.module` or `goog.declareModuleId`. */ + overlay[global] deprecated class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureModuleDeclaration { } @@ -156,6 +170,7 @@ module Closure { /** * Gets the call to `goog.module` or `goog.declareModuleId` in this module. */ + overlay[global] deprecated ClosureModuleDeclaration getModuleDeclaration() { result.getTopLevel() = this } /** @@ -181,6 +196,7 @@ module Closure { result = this.getScope().getVariable("exports") } + overlay[global] override DataFlow::Node getAnExportedValue(string name) { exists(DataFlow::PropWrite write, Expr base | result = write.getRhs() and @@ -193,6 +209,7 @@ module Closure { ) } + overlay[global] override DataFlow::Node getABulkExportedNode() { result = this.getExportsVariable().getAnAssignedExpr().flow() } @@ -232,6 +249,7 @@ module Closure { /** * Holds if `name` is a closure namespace, including proper namespace prefixes. */ + overlay[global] pragma[noinline] predicate isClosureNamespace(string name) { exists(string namespace | @@ -253,6 +271,7 @@ module Closure { * Holds if a prefix of `name` is a closure namespace. */ bindingset[name] + overlay[global] private predicate hasClosureNamespacePrefix(string name) { isClosureNamespace(name.substring(0, name.indexOf("."))) or @@ -262,6 +281,7 @@ module Closure { /** * Gets the closure namespace path addressed by the given data flow node, if any. */ + overlay[global] string getClosureNamespaceFromSourceNode(DataFlow::SourceNode node) { node = AccessPath::getAReferenceOrAssignmentTo(result) and hasClosureNamespacePrefix(result) @@ -270,6 +290,7 @@ module Closure { /** * Gets the closure namespace path written to by the given property write, if any. */ + overlay[global] string getWrittenClosureNamespace(DataFlow::PropWrite node) { node.getRhs() = AccessPath::getAnAssignmentTo(result) and hasClosureNamespacePrefix(result) @@ -278,6 +299,7 @@ module Closure { /** * Gets a data flow node that refers to the given value exported from a Closure module. */ + overlay[global] DataFlow::SourceNode moduleImport(string moduleName) { getClosureNamespaceFromSourceNode(result) = moduleName } @@ -285,6 +307,7 @@ module Closure { /** * A call to `goog.bind`, as a partial function invocation. */ + overlay[global] private class BindCall extends DataFlow::PartialInvokeNode::Range, DataFlow::CallNode { BindCall() { this = moduleImport("goog.bind").getACall() } diff --git a/javascript/ql/lib/semmle/javascript/Comments.qll b/javascript/ql/lib/semmle/javascript/Comments.qll index 889843728a25..46ce8b8a4ba9 100644 --- a/javascript/ql/lib/semmle/javascript/Comments.qll +++ b/javascript/ql/lib/semmle/javascript/Comments.qll @@ -1,4 +1,6 @@ /** Provides classes for working with JavaScript comments. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Constants.qll b/javascript/ql/lib/semmle/javascript/Constants.qll index 21e70869c67c..b0b4a6c03eec 100644 --- a/javascript/ql/lib/semmle/javascript/Constants.qll +++ b/javascript/ql/lib/semmle/javascript/Constants.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with expressions that evaluate to constant values. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/DefUse.qll b/javascript/ql/lib/semmle/javascript/DefUse.qll index a9d021f939e9..95cf57d543d2 100644 --- a/javascript/ql/lib/semmle/javascript/DefUse.qll +++ b/javascript/ql/lib/semmle/javascript/DefUse.qll @@ -1,4 +1,6 @@ /** Provides classes and predicates for working with variable definitions and uses. */ +overlay[local] +module; import javascript @@ -231,6 +233,7 @@ class VarUse extends ControlFlowNode, @varref instanceof RValue { * * For global variables, each definition is considered to reach each use. */ + overlay[global] VarDef getADef() { result = this.getSsaVariable().getDefinition().getAContributingVarDef() or result.getAVariable() = this.getVariable().(GlobalVariable) @@ -241,5 +244,6 @@ class VarUse extends ControlFlowNode, @varref instanceof RValue { * * This predicate is only defined for variables that can be SSA-converted. */ + overlay[global] SsaVariable getSsaVariable() { result.getAUse() = this } } diff --git a/javascript/ql/lib/semmle/javascript/E4X.qll b/javascript/ql/lib/semmle/javascript/E4X.qll index cd112d60664e..ce917c48cff3 100644 --- a/javascript/ql/lib/semmle/javascript/E4X.qll +++ b/javascript/ql/lib/semmle/javascript/E4X.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with E4X. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll index e584697c1e44..6eee9ea56e50 100644 --- a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll @@ -1,4 +1,6 @@ /** Provides classes for working with ECMAScript 2015 modules. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -29,11 +31,13 @@ class ES2015Module extends Module { /** Gets an export declaration in this module. */ ExportDeclaration getAnExport() { result.getTopLevel() = this } + overlay[global] override DataFlow::Node getAnExportedValue(string name) { exists(ExportDeclaration ed | ed = this.getAnExport() and result = ed.getSourceNode(name)) } /** Holds if this module exports variable `v` under the name `name`. */ + overlay[global] predicate exportsAs(LexicalName v, string name) { this.getAnExport().exportsAs(v, name) } override predicate isStrict() { @@ -50,6 +54,7 @@ class ES2015Module extends Module { * When a module has both named and `default` exports, the non-standard interpretation can lead to * ambiguities, so we only allow the standard interpretation in that case. */ + overlay[global] predicate hasBothNamedAndDefaultExports() { hasNamedExports(this) and hasDefaultExport(this) @@ -59,6 +64,7 @@ class ES2015Module extends Module { /** * Holds if `mod` contains one or more named export declarations other than `default`. */ +overlay[global] private predicate hasNamedExports(ES2015Module mod) { mod.getAnExport().(ExportNamedDeclaration).getASpecifier().getExportedName() != "default" or @@ -71,6 +77,7 @@ private predicate hasNamedExports(ES2015Module mod) { /** * Holds if this module contains a default export. */ +overlay[global] private predicate hasDefaultExport(ES2015Module mod) { // export default foo; mod.getAnExport() instanceof ExportDefaultDeclaration @@ -172,6 +179,7 @@ class ImportDeclaration extends Stmt, Import, @import_declaration { } /** A literal path expression appearing in an `import` declaration. */ +overlay[global] deprecated private class LiteralImportPath extends PathExpr, ConstantString { LiteralImportPath() { exists(ImportDeclaration req | this = req.getChildExpr(-1)) } @@ -198,6 +206,7 @@ deprecated private class LiteralImportPath extends PathExpr, ConstantString { */ class ImportSpecifier extends Expr, @import_specifier { /** Gets the import declaration in which this specifier appears. */ + overlay[global] ImportDeclaration getImportDeclaration() { result.getASpecifier() = this } /** Gets the imported symbol; undefined for default and namespace import specifiers. */ @@ -297,6 +306,7 @@ class BulkImportDeclaration extends ImportDeclaration { * import console, { log } from 'console'; * ``` */ +overlay[global] class SelectiveImportDeclaration extends ImportDeclaration { SelectiveImportDeclaration() { not this instanceof BulkImportDeclaration } @@ -330,9 +340,11 @@ class SelectiveImportDeclaration extends ImportDeclaration { */ abstract class ExportDeclaration extends Stmt, @export_declaration { /** Gets the module to which this export declaration belongs. */ + overlay[global] ES2015Module getEnclosingModule() { this = result.getAnExport() } /** Holds if this export declaration exports variable `v` under the name `name`. */ + overlay[global] abstract predicate exportsAs(LexicalName v, string name); /** @@ -356,6 +368,7 @@ abstract class ExportDeclaration extends Stmt, @export_declaration { * exports under the same name. In particular, its source node belongs * to module `a` or possibly to some other module from which `a` re-exports. */ + overlay[global] abstract DataFlow::Node getSourceNode(string name); /** Holds if is declared with the `type` keyword, so only types are exported. */ @@ -407,11 +420,13 @@ class BulkReExportDeclaration extends ReExportDeclaration, @export_all_declarati /** Gets the name of the module from which this declaration re-exports. */ override ConstantString getImportedPath() { result = this.getChildExpr(0) } + overlay[global] override predicate exportsAs(LexicalName v, string name) { this.getReExportedES2015Module().exportsAs(v, name) and not isShadowedFromBulkExport(this, name) } + overlay[global] override DataFlow::Node getSourceNode(string name) { result = this.getReExportedES2015Module().getAnExport().getSourceNode(name) } @@ -430,6 +445,7 @@ class BulkReExportDeclaration extends ReExportDeclaration, @export_all_declarati * At runtime, the interface `X` will have been removed, so `X` is actually re-exported anyway, * but we ignore this subtlety. */ +overlay[global] private predicate isShadowedFromBulkExport(BulkReExportDeclaration reExport, string name) { exists(ExportNamedDeclaration other | other.getTopLevel() = reExport.getEnclosingModule() | other.getAnExportedDecl().getName() = name @@ -452,6 +468,7 @@ class ExportDefaultDeclaration extends ExportDeclaration, @export_default_declar /** Gets the operand statement or expression that is exported by this declaration. */ ExprOrStmt getOperand() { result = this.getChild(0) } + overlay[global] override predicate exportsAs(LexicalName v, string name) { name = "default" and v = this.getADecl().getVariable() } @@ -464,6 +481,7 @@ class ExportDefaultDeclaration extends ExportDeclaration, @export_default_declar ) } + overlay[global] override DataFlow::Node getSourceNode(string name) { name = "default" and result = DataFlow::valueNode(this.getOperand()) } @@ -506,6 +524,7 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio /** Gets the variable declaration, if any, exported by this named export. */ VarDecl getADecl() { result = this.getAnExportedDecl() } + overlay[global] override predicate exportsAs(LexicalName v, string name) { exists(LexicalDecl vd | vd = this.getAnExportedDecl() | name = vd.getName() and v = vd.getALexicalName() @@ -518,6 +537,7 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio ) } + overlay[global] override DataFlow::Node getSourceNode(string name) { exists(VarDef d | d.getTarget() = this.getADecl() | name = d.getTarget().(VarDecl).getName() and @@ -555,6 +575,7 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio private import semmle.javascript.dataflow.internal.PreCallGraphStep +overlay[global] private class ExportNamespaceStep extends PreCallGraphStep { override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { exists(ExportNamedDeclaration exprt, ExportNamespaceSpecifier spec | @@ -572,6 +593,7 @@ private class ExportNamespaceStep extends PreCallGraphStep { private class TypeOnlyExportDeclaration extends ExportNamedDeclaration { TypeOnlyExportDeclaration() { this.isTypeOnly() } + overlay[global] override predicate exportsAs(LexicalName v, string name) { super.exportsAs(v, name) and not v instanceof Variable @@ -745,9 +767,11 @@ abstract class ReExportDeclaration extends ExportDeclaration { abstract ConstantString getImportedPath(); /** Gets the module from which this declaration re-exports, if it is an ES2015 module. */ + overlay[global] ES2015Module getReExportedES2015Module() { result = this.getReExportedModule() } /** Gets the module from which this declaration re-exports. */ + overlay[global] cached Module getReExportedModule() { Stages::Imports::ref() and @@ -756,6 +780,7 @@ abstract class ReExportDeclaration extends ExportDeclaration { } /** A literal path expression appearing in a re-export declaration. */ +overlay[global] deprecated private class LiteralReExportPath extends PathExpr, ConstantString { LiteralReExportPath() { exists(ReExportDeclaration bred | this = bred.getImportedPath()) } @@ -795,11 +820,13 @@ class SelectiveReExportDeclaration extends ReExportDeclaration, ExportNamedDecla class OriginalExportDeclaration extends ExportDeclaration { OriginalExportDeclaration() { not this instanceof ReExportDeclaration } + overlay[global] override predicate exportsAs(LexicalName v, string name) { this.(ExportDefaultDeclaration).exportsAs(v, name) or this.(ExportNamedDeclaration).exportsAs(v, name) } + overlay[global] override DataFlow::Node getSourceNode(string name) { result = this.(ExportDefaultDeclaration).getSourceNode(name) or result = this.(ExportNamedDeclaration).getSourceNode(name) diff --git a/javascript/ql/lib/semmle/javascript/Errors.qll b/javascript/ql/lib/semmle/javascript/Errors.qll index 6a5d73566a44..518b76b53461 100644 --- a/javascript/ql/lib/semmle/javascript/Errors.qll +++ b/javascript/ql/lib/semmle/javascript/Errors.qll @@ -1,4 +1,6 @@ /** Provides classes for working with syntax errors. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Expr.qll b/javascript/ql/lib/semmle/javascript/Expr.qll index ae02511ba410..177ef6991ce3 100644 --- a/javascript/ql/lib/semmle/javascript/Expr.qll +++ b/javascript/ql/lib/semmle/javascript/Expr.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with expressions. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -115,12 +117,14 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { string getStringValue() { Stages::Ast::ref() and result = getStringValue(this) } /** Holds if this expression is impure, that is, its evaluation could have side effects. */ + overlay[global] predicate isImpure() { any() } /** * Holds if this expression is pure, that is, its evaluation is guaranteed * to be side-effect free. */ + overlay[global] predicate isPure() { not this.isImpure() } /** @@ -153,21 +157,25 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { * Holds if this expression accesses the global variable `g`, either directly * or through the `window` object. */ + overlay[global] predicate accessesGlobal(string g) { this.flow().accessesGlobal(g) } /** * Holds if this expression may evaluate to `s`. */ + overlay[global] predicate mayHaveStringValue(string s) { this.flow().mayHaveStringValue(s) } /** * Holds if this expression may evaluate to `b`. */ + overlay[global] predicate mayHaveBooleanValue(boolean b) { this.flow().mayHaveBooleanValue(b) } /** * Holds if this expression may refer to the initial value of parameter `p`. */ + overlay[global] predicate mayReferToParameter(Parameter p) { DataFlow::parameterNode(p).flowsToExpr(this) } /** @@ -178,6 +186,7 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { * Has no result if the expression is in a JavaScript file or in a TypeScript * file that was extracted without type information. */ + overlay[global] deprecated Type getType() { ast_node_type(this, result) } /** @@ -250,6 +259,7 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { * Gets the data-flow node where exceptions thrown by this expression will * propagate if this expression causes an exception to be thrown. */ + overlay[caller] pragma[inline] DataFlow::Node getExceptionTarget() { result = getCatchParameterFromStmt(this.getRawEnclosingStmt(this)) @@ -301,6 +311,7 @@ class Identifier extends @identifier, ExprOrType { * ``` */ class Label extends @label, Identifier, Expr { + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "Label" } @@ -330,6 +341,7 @@ class Literal extends @literal, Expr { */ string getRawValue() { literals(_, result, this) } + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "Literal" } @@ -352,6 +364,7 @@ class ParExpr extends @par_expr, Expr { override int getIntValue() { result = this.getExpression().getIntValue() } + overlay[global] override predicate isImpure() { this.getExpression().isImpure() } override Expr getUnderlyingValue() { result = this.getExpression().getUnderlyingValue() } @@ -500,6 +513,7 @@ class RegExpLiteral extends @regexp_literal, Literal, RegExpParent { * ``` */ class ThisExpr extends @this_expr, Expr { + overlay[global] override predicate isImpure() { none() } /** @@ -555,6 +569,7 @@ class ArrayExpr extends @array_expr, Expr { /** Holds if this array literal has an omitted element. */ predicate hasOmittedElement() { this.elementIsOmitted(_) } + overlay[global] override predicate isImpure() { this.getAnElement().isImpure() } override string getAPrimaryQlClass() { result = "ArrayExpr" } @@ -597,6 +612,7 @@ class ObjectExpr extends @obj_expr, Expr { */ predicate hasTrailingComma() { this.getLastToken().getPreviousToken().getValue() = "," } + overlay[global] override predicate isImpure() { this.getAProperty().isImpure() } override string getAPrimaryQlClass() { result = "ObjectExpr" } @@ -664,6 +680,7 @@ class Property extends @property, Documentable { * Holds if this property is impure, that is, the evaluation of its name or * its initializer expression could have side effects. */ + overlay[global] predicate isImpure() { this.isComputed() and this.getNameExpr().isImpure() or @@ -826,6 +843,7 @@ class FunctionExpr extends @function_expr, Expr, Function { Stages::Ast::ref() and result = Expr.super.getContainer() } + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "FunctionExpr" } @@ -846,6 +864,7 @@ class ArrowFunctionExpr extends @arrow_function_expr, Expr, Function { override StmtContainer getEnclosingContainer() { result = Expr.super.getContainer() } + overlay[global] override predicate isImpure() { none() } override Function getThisBinder() { @@ -877,6 +896,7 @@ class SeqExpr extends @seq_expr, Expr { /** Gets the last expression in this sequence. */ Expr getLastOperand() { result = this.getOperand(this.getNumOperands() - 1) } + overlay[global] override predicate isImpure() { this.getAnOperand().isImpure() } override Expr getUnderlyingValue() { result = this.getLastOperand().getUnderlyingValue() } @@ -906,6 +926,7 @@ class ConditionalExpr extends @conditional_expr, Expr { /** Gets either the 'then' or the 'else' expression of this conditional. */ Expr getABranch() { result = this.getConsequent() or result = this.getAlternate() } + overlay[global] override predicate isImpure() { this.getCondition().isImpure() or this.getABranch().isImpure() @@ -985,6 +1006,7 @@ class InvokeExpr extends @invokeexpr, Expr { * * This predicate is an approximation, computed using only local data flow. */ + overlay[global] predicate hasOptionArgument(int i, string name, Expr value) { value = this.flow().(DataFlow::InvokeNode).getOptionArgument(i, name).asExpr() } @@ -997,6 +1019,7 @@ class InvokeExpr extends @invokeexpr, Expr { * * This predicate is only populated for files extracted with full TypeScript extraction. */ + overlay[global] deprecated CallSignatureType getResolvedSignature() { invoke_expr_signature(this, result) } /** @@ -1014,6 +1037,7 @@ class InvokeExpr extends @invokeexpr, Expr { * * This predicate is only populated for files extracted with full TypeScript extraction. */ + overlay[global] deprecated CanonicalFunctionName getResolvedCalleeName() { ast_node_symbol(this, result) } /** @@ -1022,6 +1046,7 @@ class InvokeExpr extends @invokeexpr, Expr { * Note that the resolved function may be overridden in a subclass and thus is not * necessarily the actual target of this invocation at runtime. */ + overlay[global] Function getResolvedCallee() { TypeResolution::callTarget(this, result) } } @@ -1156,6 +1181,7 @@ class DotExpr extends @dot_expr, PropAccess { /** Gets the identifier specifying the name of the accessed property. */ Identifier getProperty() { result = this.getChildExpr(1) } + overlay[global] override predicate isImpure() { this.getBase().isImpure() } override string getAPrimaryQlClass() { result = "DotExpr" } @@ -1176,6 +1202,7 @@ class IndexExpr extends @index_expr, PropAccess { override string getPropertyName() { result = this.getIndex().(Literal).getValue() } + overlay[global] override predicate isImpure() { this.getBase().isImpure() or this.getIndex().isImpure() @@ -1201,6 +1228,7 @@ class UnaryExpr extends @unaryexpr, Expr { /** Gets the operator of this expression. */ string getOperator() { none() } + overlay[global] override predicate isImpure() { this.getOperand().isImpure() } override ControlFlowNode getFirstControlFlowNode() { @@ -1302,6 +1330,7 @@ class VoidExpr extends @void_expr, UnaryExpr { class DeleteExpr extends @delete_expr, UnaryExpr { override string getOperator() { result = "delete" } + overlay[global] override predicate isImpure() { any() } } @@ -1352,6 +1381,7 @@ class BinaryExpr extends @binaryexpr, Expr { /** Gets the operator of this expression. */ string getOperator() { none() } + overlay[global] override predicate isImpure() { this.getAnOperand().isImpure() } override ControlFlowNode getFirstControlFlowNode() { @@ -2233,6 +2263,7 @@ class YieldExpr extends @yield_expr, Expr { /** Holds if this is a `yield*` expression. */ predicate isDelegating() { is_delegating(this) } + overlay[global] override predicate isImpure() { any() } override ControlFlowNode getFirstControlFlowNode() { @@ -2289,6 +2320,7 @@ class ComprehensionExpr extends @comprehension_expr, Expr { /** Gets the body expression of this comprehension. */ Expr getBody() { result = this.getChildExpr(0) } + overlay[global] override predicate isImpure() { this.getABlock().isImpure() or this.getAFilter().isImpure() or @@ -2349,6 +2381,7 @@ class ComprehensionBlock extends @comprehension_block, Expr { /** Gets the domain over which this comprehension block iterates. */ Expr getDomain() { result = this.getChildExpr(1) } + overlay[global] override predicate isImpure() { this.getIterator().isImpure() or this.getDomain().isImpure() @@ -2675,6 +2708,7 @@ class AwaitExpr extends @await_expr, Expr { /** Gets the operand of this `await` expression. */ Expr getOperand() { result = this.getChildExpr(0) } + overlay[global] override predicate isImpure() { any() } override ControlFlowNode getFirstControlFlowNode() { @@ -2698,6 +2732,7 @@ class AwaitExpr extends @await_expr, Expr { * ``` */ class FunctionSentExpr extends @function_sent_expr, Expr { + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "FunctionSentExpr" } @@ -2857,6 +2892,7 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import { } /** A literal path expression appearing in a dynamic import. */ +overlay[global] deprecated private class LiteralDynamicImportPath extends PathExpr, ConstantString { LiteralDynamicImportPath() { exists(DynamicImportExpr di | this.getParentExpr*() = di.getSource()) @@ -2919,6 +2955,7 @@ class OptionalChainRoot extends ChainElem { * ``` */ class ImportMetaExpr extends @import_meta_expr, Expr { + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "ImportMetaExpr" } diff --git a/javascript/ql/lib/semmle/javascript/Externs.qll b/javascript/ql/lib/semmle/javascript/Externs.qll index a2a2533d8494..f894107528c4 100644 --- a/javascript/ql/lib/semmle/javascript/Externs.qll +++ b/javascript/ql/lib/semmle/javascript/Externs.qll @@ -36,6 +36,8 @@ * Array.prototype.length; * */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Files.qll b/javascript/ql/lib/semmle/javascript/Files.qll index b9274d92ebaa..8cc14ca0492b 100644 --- a/javascript/ql/lib/semmle/javascript/Files.qll +++ b/javascript/ql/lib/semmle/javascript/Files.qll @@ -1,4 +1,6 @@ /** Provides classes for working with files and folders. */ +overlay[local] +module; import javascript private import NodeModuleResolutionImpl @@ -33,12 +35,14 @@ module Folder = Impl::Folder; /** A folder. */ class Folder extends Container, Impl::Folder { /** Gets the file or subfolder in this folder that has the given `name`, if any. */ + overlay[global] Container getChildContainer(string name) { result = this.getAChildContainer() and result.getBaseName() = name } /** Gets the file in this folder that has the given `stem` and `extension`, if any. */ + overlay[global] File getFile(string stem, string extension) { result = this.getAChildContainer() and result.getStem() = stem and @@ -46,6 +50,7 @@ class Folder extends Container, Impl::Folder { } /** Like `getFile` except `d.ts` is treated as a single extension. */ + overlay[global] private File getFileLongExtension(string stem, string extension) { not (stem.matches("%.d") and extension = "ts") and result = this.getFile(stem, extension) @@ -65,6 +70,7 @@ class Folder extends Container, Impl::Folder { * * HTML files will not be found by this method. */ + overlay[global] File getJavaScriptFile(string stem) { result = min(int p, string ext | @@ -78,6 +84,7 @@ class Folder extends Container, Impl::Folder { * Gets an implementation file and/or a typings file from this folder that has the given `stem`. * This could be a single `.ts` file or a pair of `.js` and `.d.ts` files. */ + overlay[global] File getJavaScriptFileOrTypings(string stem) { exists(File jsFile | jsFile = this.getJavaScriptFile(stem) | result = jsFile @@ -88,6 +95,7 @@ class Folder extends Container, Impl::Folder { } /** Gets a subfolder contained in this folder. */ + overlay[global] Folder getASubFolder() { result = this.getAChildContainer() } } diff --git a/javascript/ql/lib/semmle/javascript/Functions.qll b/javascript/ql/lib/semmle/javascript/Functions.qll index b72bfbc888e9..9b1f98c3d0b6 100644 --- a/javascript/ql/lib/semmle/javascript/Functions.qll +++ b/javascript/ql/lib/semmle/javascript/Functions.qll @@ -1,4 +1,6 @@ /** Provides classes for working with functions. */ +overlay[local] +module; import javascript @@ -434,11 +436,13 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine * * This predicate is only populated for files extracted with full TypeScript extraction. */ + overlay[global] deprecated CanonicalFunctionName getCanonicalName() { ast_node_symbol(this, result) } /** * Gets the call signature of this function, as determined by the TypeScript compiler, if any. */ + overlay[global] deprecated CallSignatureType getCallSignature() { declared_function_signature(this, result) } } diff --git a/javascript/ql/lib/semmle/javascript/HTML.qll b/javascript/ql/lib/semmle/javascript/HTML.qll index 43b66db459ff..8f70150963ef 100644 --- a/javascript/ql/lib/semmle/javascript/HTML.qll +++ b/javascript/ql/lib/semmle/javascript/HTML.qll @@ -1,4 +1,6 @@ /** Provides classes for working with HTML documents. */ +overlay[local] +module; import javascript @@ -283,6 +285,7 @@ module HTML { /** * A path string arising from the `src` attribute of a `script` tag. */ + overlay[global] deprecated private class ScriptSrcPath extends PathString { ScriptSrcPath() { scriptSrc(this, _) } diff --git a/javascript/ql/lib/semmle/javascript/JSDoc.qll b/javascript/ql/lib/semmle/javascript/JSDoc.qll index 85b7695cd70e..f63e24d9c6c0 100644 --- a/javascript/ql/lib/semmle/javascript/JSDoc.qll +++ b/javascript/ql/lib/semmle/javascript/JSDoc.qll @@ -1,4 +1,6 @@ /** Provides classes for working with JSDoc comments. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -627,6 +629,7 @@ module JSDoc { /** * A statement container which may declare JSDoc name aliases. */ + overlay[global] deprecated class Environment extends StmtContainer { /** * Gets the fully qualified name aliased by the given unqualified name diff --git a/javascript/ql/lib/semmle/javascript/JSON.qll b/javascript/ql/lib/semmle/javascript/JSON.qll index 19fc3ec84d7a..ca322bacd467 100644 --- a/javascript/ql/lib/semmle/javascript/JSON.qll +++ b/javascript/ql/lib/semmle/javascript/JSON.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSON data. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/JSX.qll b/javascript/ql/lib/semmle/javascript/JSX.qll index ed8a7b097a6b..d182f1553543 100644 --- a/javascript/ql/lib/semmle/javascript/JSX.qll +++ b/javascript/ql/lib/semmle/javascript/JSX.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSX code. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Lines.qll b/javascript/ql/lib/semmle/javascript/Lines.qll index 1db9187008a1..272be691498b 100644 --- a/javascript/ql/lib/semmle/javascript/Lines.qll +++ b/javascript/ql/lib/semmle/javascript/Lines.qll @@ -4,6 +4,8 @@ * This information is only available for snapshots that have been extracted with * the `--extract-program-text` flag. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Locations.qll b/javascript/ql/lib/semmle/javascript/Locations.qll index a3ad79ef93ea..87b41c2cb43f 100644 --- a/javascript/ql/lib/semmle/javascript/Locations.qll +++ b/javascript/ql/lib/semmle/javascript/Locations.qll @@ -1,4 +1,6 @@ /** Provides classes for working with locations and program elements that have locations. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Modules.qll b/javascript/ql/lib/semmle/javascript/Modules.qll index 8b0330b708ba..bc69695121e7 100644 --- a/javascript/ql/lib/semmle/javascript/Modules.qll +++ b/javascript/ql/lib/semmle/javascript/Modules.qll @@ -3,6 +3,8 @@ * ECMAScript 2015-style modules, and the older CommonJS and AMD-style * modules. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -23,9 +25,11 @@ abstract class Module extends TopLevel { Import getAnImport() { result.getTopLevel() = this } /** Gets a module from which this module imports. */ + overlay[global] Module getAnImportedModule() { result = this.getAnImport().getImportedModule() } /** Gets a symbol exported by this module. */ + overlay[global] string getAnExportedSymbol() { exists(this.getAnExportedValue(result)) } /** @@ -39,12 +43,14 @@ abstract class Module extends TopLevel { * Symbols defined in another module that are re-exported by * this module are only sometimes considered. */ + overlay[global] cached abstract DataFlow::Node getAnExportedValue(string name); /** * Gets a value that is exported as the whole exports object of this module. */ + overlay[global] cached DataFlow::Node getABulkExportedNode() { none() } // overridden in subclasses @@ -55,6 +61,7 @@ abstract class Module extends TopLevel { * This can be used to determine which value a default-import will likely refer to, * as the interaction between different module types is not standardized. */ + overlay[global] DataFlow::Node getDefaultOrBulkExport() { result = [this.getAnExportedValue("default"), this.getABulkExportedNode()] } @@ -69,6 +76,7 @@ abstract class Module extends TopLevel { * This predicate is not part of the public API, it is only exposed to allow * overriding by subclasses. */ + overlay[global] deprecated predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { path.getEnclosingModule() = this and priority = 0 and @@ -90,6 +98,7 @@ abstract class Module extends TopLevel { * resolves to a folder containing a main module (such as `index.js`), then * that file is the result. */ + overlay[global] deprecated File resolve(PathExpr path) { path.getEnclosingModule() = this and ( @@ -124,6 +133,7 @@ abstract class Import extends AstNode { abstract Module getEnclosingModule(); /** DEPRECATED. Use `getImportedPathExpr` instead. */ + overlay[global] deprecated PathExpr getImportedPath() { result = this.getImportedPathExpr() } /** Gets the (unresolved) path that this import refers to. */ @@ -138,6 +148,7 @@ abstract class Import extends AstNode { * Any externs module whose name exactly matches the imported * path is assumed to be a possible target of the import. */ + overlay[global] Module resolveExternsImport() { result.isExterns() and result.getName() = this.getImportedPathString() } @@ -145,16 +156,19 @@ abstract class Import extends AstNode { /** * Gets the module the path of this import resolves to. */ + overlay[global] Module resolveImportedPath() { result.getFile() = this.getImportedFile() } /** * Gets the module the path of this import resolves to. */ + overlay[global] File getImportedFile() { result = ImportPathResolver::resolveExpr(this.getImportedPathExpr()) } /** * DEPRECATED. Use `getImportedModule()` instead. */ + overlay[global] deprecated Module resolveFromTypeScriptSymbol() { exists(CanonicalName symbol | ast_node_symbol(this, symbol) and @@ -170,6 +184,7 @@ abstract class Import extends AstNode { * behavior of Node.js imports, which prefer core modules such as `fs` over any * source module of the same name. */ + overlay[global] cached Module getImportedModule() { Stages::Imports::ref() and @@ -210,6 +225,7 @@ abstract class Import extends AstNode { * in cases where it would cause ambiguity between named exports and properties * of a default export. */ + overlay[global] final DataFlow::Node getImportedModuleNodeStrict() { result = this.getImportedModuleNode() and not ( diff --git a/javascript/ql/lib/semmle/javascript/NPM.qll b/javascript/ql/lib/semmle/javascript/NPM.qll index cbe580b45689..857fc1638047 100644 --- a/javascript/ql/lib/semmle/javascript/NPM.qll +++ b/javascript/ql/lib/semmle/javascript/NPM.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with NPM module definitions and dependencies. */ +overlay[local?] +module; import javascript private import NodeModuleResolutionImpl diff --git a/javascript/ql/lib/semmle/javascript/NodeJS.qll b/javascript/ql/lib/semmle/javascript/NodeJS.qll index 7e9e2fdea904..dfc2dd15ad36 100644 --- a/javascript/ql/lib/semmle/javascript/NodeJS.qll +++ b/javascript/ql/lib/semmle/javascript/NodeJS.qll @@ -17,6 +17,7 @@ private import semmle.javascript.dataflow.internal.DataFlowNode * process.stdout.write(fs.readFileSync(process.argv[i], 'utf8')); * ``` */ +overlay[local] class NodeModule extends Module { NodeModule() { is_module(this) and @@ -36,11 +37,13 @@ class NodeModule extends Module { * Gets an abstract value representing one or more values that may flow * into this module's `module.exports` property. */ + overlay[global] pragma[noinline] DefiniteAbstractValue getAModuleExportsValue() { result = this.getAModuleExportsProperty().getAValue() } + overlay[global] pragma[noinline] private AbstractProperty getAModuleExportsProperty() { result.getBase().(AbstractModuleObject).getModule() = this and @@ -52,12 +55,14 @@ class NodeModule extends Module { * For performance this predicate only computes relevant expressions (in `getAModuleExportsCandidate`). * So if using this predicate - consider expanding the list of relevant expressions. */ + overlay[global] DataFlow::AnalyzedNode getAModuleExportsNode() { result = getAModuleExportsCandidate() and result.getAValue() = this.getAModuleExportsValue() } /** Gets a symbol exported by this module. */ + overlay[global] override string getAnExportedSymbol() { result = super.getAnExportedSymbol() or @@ -70,6 +75,7 @@ class NodeModule extends Module { ) } + overlay[global] override DataFlow::Node getAnExportedValue(string name) { // a property write whose base is `exports` or `module.exports` exists(DataFlow::PropWrite pwn | result = pwn.getRhs() | @@ -114,6 +120,7 @@ class NodeModule extends Module { ) } + overlay[global] override DataFlow::Node getABulkExportedNode() { Stages::Imports::ref() and exists(DataFlow::PropWrite write | @@ -124,6 +131,7 @@ class NodeModule extends Module { } /** Gets a symbol that the module object inherits from its prototypes. */ + overlay[global] private string getAnImplicitlyExportedSymbol() { exists(ExternalConstructor ec | ec = this.getPrototypeOfExportedExpr() | result = ec.getAMember().getName() @@ -136,6 +144,7 @@ class NodeModule extends Module { } /** Gets an externs declaration of the prototype object of a value exported by this module. */ + overlay[global] private ExternalConstructor getPrototypeOfExportedExpr() { exists(AbstractValue exported | exported = this.getAModuleExportsValue() | result instanceof ObjectExternal @@ -146,6 +155,7 @@ class NodeModule extends Module { ) } + overlay[global] deprecated override predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { path.getEnclosingModule() = this and exists(string pathval | pathval = path.getValue() | @@ -224,6 +234,7 @@ predicate findNodeModulesFolder(Folder f, Folder nodeModules, int distance) { /** * A Node.js `require` variable. */ +overlay[local] private class RequireVariable extends Variable { RequireVariable() { this = any(ModuleScope m).getVariable("require") @@ -236,6 +247,7 @@ private class RequireVariable extends Variable { } } +overlay[local] private predicate isModuleModule(EarlyStageNode nd) { exists(ImportDeclaration imp | imp.getRawImportPath() = "module" | nd = TDestructuredModuleImportNode(imp) @@ -249,6 +261,7 @@ private predicate isModuleModule(EarlyStageNode nd) { ) } +overlay[local] private predicate isCreateRequire(EarlyStageNode nd) { exists(PropAccess prop | isModuleModule(TValueNode(prop.getBase())) and @@ -278,6 +291,7 @@ private predicate isCreateRequire(EarlyStageNode nd) { /** * Holds if `nd` may refer to `require`, either directly or modulo local data flow. */ +overlay[local] cached private predicate isRequire(EarlyStageNode nd) { exists(VarAccess access | @@ -320,6 +334,7 @@ private predicate isRequire(EarlyStageNode nd) { * require('fs') * ``` */ +overlay[local] class Require extends CallExpr, Import { Require() { isRequire(TValueNode(this.getCallee())) } diff --git a/javascript/ql/lib/semmle/javascript/Promises.qll b/javascript/ql/lib/semmle/javascript/Promises.qll index 2feb92e2e553..dfdcdfd632cb 100644 --- a/javascript/ql/lib/semmle/javascript/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/Promises.qll @@ -186,11 +186,13 @@ module Promises { /** * Gets the pseudo-field used to describe resolved values in a promise. */ + overlay[local] string valueProp() { result = "$PromiseResolveField$" } /** * Gets the pseudo-field used to describe rejected values in a promise. */ + overlay[local] string errorProp() { result = "$PromiseRejectField$" } /** A property set containing the pseudo-properites of a promise object. */ diff --git a/javascript/ql/lib/semmle/javascript/Regexp.qll b/javascript/ql/lib/semmle/javascript/Regexp.qll index ea2993ae7da8..dba2c853008d 100644 --- a/javascript/ql/lib/semmle/javascript/Regexp.qll +++ b/javascript/ql/lib/semmle/javascript/Regexp.qll @@ -4,6 +4,8 @@ * Regular expression literals are represented as an abstract syntax tree of regular expression * terms. */ +overlay[local] +module; import javascript private import semmle.javascript.dataflow.InferredTypes @@ -150,6 +152,7 @@ class RegExpTerm extends Locatable, @regexpterm { * /[a-z]+/g; // YES - Regexp literals are always used as regexp * ``` */ + overlay[global] predicate isUsedAsRegExp() { exists(RegExpParent parent | parent = this.getRootTerm().getParent() | parent instanceof RegExpLiteral @@ -964,6 +967,7 @@ class RegExpParseError extends Error, @regexp_parse_error { /** * Holds if `func` is a method defined on `String.prototype` with name `name`. */ +overlay[global] private predicate isNativeStringMethod(Function func, string name) { exists(ExternalInstanceMemberDecl decl | decl.hasQualifiedName("String", name) and @@ -975,6 +979,7 @@ private predicate isNativeStringMethod(Function func, string name) { * Holds if `name` is the name of a property on a Match object returned by `String.prototype.match`, * not including array indices. */ +overlay[global] private predicate isMatchObjectProperty(string name) { any(ExternalInstanceMemberDecl decl).hasQualifiedName("Array", name) or @@ -982,6 +987,7 @@ private predicate isMatchObjectProperty(string name) { } /** Holds if `call` is a call to `match` whose result is used in a way that is incompatible with Match objects. */ +overlay[global] private predicate isUsedAsNonMatchObject(DataFlow::MethodCallNode call) { call.getMethodName() = ["match", "matchAll"] and call.getNumArgument() = 1 and @@ -1006,6 +1012,7 @@ private predicate isUsedAsNonMatchObject(DataFlow::MethodCallNode call) { /** * Holds if `value` is used in a way that suggests it returns a number. */ +overlay[global] pragma[inline] private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) { any(Comparison compare) @@ -1027,6 +1034,7 @@ private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) { /** * Holds if `source` may be interpreted as a regular expression. */ +overlay[global] cached predicate isInterpretedAsRegExp(DataFlow::Node source) { Stages::Taint::ref() and @@ -1073,6 +1081,7 @@ predicate isInterpretedAsRegExp(DataFlow::Node source) { * Gets a node whose value may flow (inter-procedurally) to `re`, where it is interpreted * as a part of a regular expression. */ +overlay[global] private DataFlow::Node regExpSource(DataFlow::Node re, DataFlow::TypeBackTracker t) { t.start() and re = result and @@ -1090,6 +1099,7 @@ private DataFlow::Node regExpSource(DataFlow::Node re, DataFlow::TypeBackTracker * Gets a node whose value may flow (inter-procedurally) to `re`, where it is interpreted * as a part of a regular expression. */ +overlay[global] private DataFlow::Node regExpSource(DataFlow::Node re) { result = regExpSource(re, DataFlow::TypeBackTracker::end()) } @@ -1098,6 +1108,7 @@ private DataFlow::Node regExpSource(DataFlow::Node re) { * A node whose value may flow to a position where it is interpreted * as a part of a regular expression. */ +overlay[global] abstract class RegExpPatternSource extends DataFlow::Node { /** * Gets a node where the pattern of this node is parsed as a part of @@ -1126,6 +1137,7 @@ abstract class RegExpPatternSource extends DataFlow::Node { /** * A regular expression literal, viewed as the pattern source for itself. */ +overlay[global] private class RegExpLiteralPatternSource extends RegExpPatternSource, DataFlow::ValueNode { override RegExpLiteral astNode; @@ -1145,6 +1157,7 @@ private class RegExpLiteralPatternSource extends RegExpPatternSource, DataFlow:: * A node whose string value may flow to a position where it is interpreted * as a part of a regular expression. */ +overlay[global] private class StringRegExpPatternSource extends RegExpPatternSource { DataFlow::Node parse; @@ -1169,6 +1182,7 @@ private class StringRegExpPatternSource extends RegExpPatternSource { * A node whose string value may flow to a position where it is interpreted * as a part of a regular expression. */ +overlay[global] private class StringConcatRegExpPatternSource extends RegExpPatternSource { DataFlow::Node parse; @@ -1331,6 +1345,7 @@ module RegExp { /** * Gets the AST of a regular expression object that can flow to `node`. */ + overlay[global] RegExpTerm getRegExpObjectFromNode(DataFlow::Node node) { exists(DataFlow::RegExpCreationNode regexp | regexp.getAReference().flowsTo(node) and @@ -1342,6 +1357,7 @@ module RegExp { * Gets the AST of a regular expression that can flow to `node`, * including `RegExp` objects as well as strings interpreted as regular expressions. */ + overlay[global] RegExpTerm getRegExpFromNode(DataFlow::Node node) { result = getRegExpObjectFromNode(node) or diff --git a/javascript/ql/lib/semmle/javascript/SSA.qll b/javascript/ql/lib/semmle/javascript/SSA.qll index a2c5bf1d34e6..52486a7b7e3b 100644 --- a/javascript/ql/lib/semmle/javascript/SSA.qll +++ b/javascript/ql/lib/semmle/javascript/SSA.qll @@ -73,6 +73,8 @@ * expression in `k` induces a re-capture of `x` to reflect the fact that `x` * is incremented between the two `console.log` calls. */ +overlay[local] +module; import javascript private import semmle.javascript.dataflow.Refinements diff --git a/javascript/ql/lib/semmle/javascript/Stmt.qll b/javascript/ql/lib/semmle/javascript/Stmt.qll index 93eb1d1dea07..f97b07ac8e94 100644 --- a/javascript/ql/lib/semmle/javascript/Stmt.qll +++ b/javascript/ql/lib/semmle/javascript/Stmt.qll @@ -1,4 +1,6 @@ /** Provides classes for working with statements. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Templates.qll b/javascript/ql/lib/semmle/javascript/Templates.qll index 5e2b4a2d8aae..1b3db059226b 100644 --- a/javascript/ql/lib/semmle/javascript/Templates.qll +++ b/javascript/ql/lib/semmle/javascript/Templates.qll @@ -1,4 +1,6 @@ /** Provides classes for working with ECMAScript 2015-style template expressions. */ +overlay[local] +module; import javascript @@ -58,6 +60,7 @@ class TemplateLiteral extends Expr, @template_literal { */ int getNumElement() { result = count(this.getAnElement()) } + overlay[global] override predicate isImpure() { this.getAnElement().isImpure() } override string getAPrimaryQlClass() { result = "TemplateLiteral" } diff --git a/javascript/ql/lib/semmle/javascript/Tokens.qll b/javascript/ql/lib/semmle/javascript/Tokens.qll index c9eeef69dfba..4e1c63440b5b 100644 --- a/javascript/ql/lib/semmle/javascript/Tokens.qll +++ b/javascript/ql/lib/semmle/javascript/Tokens.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with the token-based representation of JavaScript programs. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll b/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll index 6d0a13c4a38f..50201363bea1 100644 --- a/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll +++ b/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about type annotations independently of dialect. */ +overlay[local] +module; import javascript private import internal.StmtContainers @@ -18,6 +20,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * This can be used to map a type name to the class/interface it refers to, or * associate it with a named type coming from an dependency. */ + overlay[global] TypeNameBindingNode getTypeBinding() { result = this } /** Holds if this is the `any` type. */ @@ -90,6 +93,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * * Holds if this is a reference to the type with qualified name `globalName` relative to the global scope. */ + overlay[global] deprecated predicate hasQualifiedName(string globalName) { UnderlyingTypes::nodeHasUnderlyingType(this, globalName) } @@ -99,6 +103,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * * Holds if this is a reference to the type exported from `moduleName` under the name `exportedName`. */ + overlay[global] deprecated predicate hasQualifiedName(string moduleName, string exportedName) { UnderlyingTypes::nodeHasUnderlyingType(this, moduleName, exportedName) } @@ -107,6 +112,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * Holds if this is a reference to the type with qualified name `globalName` relative to the global scope, * or is declared as a subtype thereof, or is a union or intersection containing such a type. */ + overlay[global] final predicate hasUnderlyingType(string globalName) { UnderlyingTypes::nodeHasUnderlyingType(this, globalName) } @@ -115,6 +121,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * Holds if this is a reference to the type exported from `moduleName` under the name `exportedName`, * or is declared as a subtype thereof, or is a union or intersection containing such a type. */ + overlay[global] final predicate hasUnderlyingType(string moduleName, string exportedName) { UnderlyingTypes::nodeHasUnderlyingType(this, moduleName, exportedName) } @@ -135,6 +142,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * * Note that this has no result for JSDoc type annotations. */ + overlay[global] deprecated Type getType() { none() } /** @@ -142,5 +150,6 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * * This unfolds nullability modifiers and generic type applications. */ + overlay[global] final DataFlow::ClassNode getClass() { UnderlyingTypes::nodeHasUnderlyingClassType(this, result) } } diff --git a/javascript/ql/lib/semmle/javascript/TypeScript.qll b/javascript/ql/lib/semmle/javascript/TypeScript.qll index 79b71fcd8c05..b9d6ea0af983 100644 --- a/javascript/ql/lib/semmle/javascript/TypeScript.qll +++ b/javascript/ql/lib/semmle/javascript/TypeScript.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import javascript /** @@ -31,6 +34,7 @@ class NamespaceDefinition extends Stmt, @namespace_definition, AST::ValueNode { /** * Gets the canonical name of the namespace being defined. */ + overlay[global] deprecated Namespace getNamespace() { result.getADefinition() = this } } @@ -111,11 +115,13 @@ class TypeDefinition extends AstNode, @type_definition { /** * Gets the canonical name of the type being defined. */ + overlay[global] deprecated TypeName getTypeName() { result.getADefinition() = this } /** * Gets the type defined by this declaration. */ + overlay[global] deprecated Type getType() { ast_node_type(this.getIdentifier(), result) } override string getAPrimaryQlClass() { result = "TypeDefinition" } @@ -221,6 +227,7 @@ class ExternalModuleReference extends Expr, Import, @external_module_reference { } /** A literal path expression appearing in an external module reference. */ +overlay[global] deprecated private class LiteralExternalModulePath extends PathExpr, ConstantString { LiteralExternalModulePath() { exists(ExternalModuleReference emr | this.getParentExpr*() = emr.getExpression()) @@ -268,6 +275,7 @@ class TypeAliasDeclaration extends @type_alias_declaration, TypeParameterized, S /** * Gets the canonical name of the type being defined. */ + overlay[global] deprecated TypeName getTypeName() { result.getADefinition() = this } override string getAPrimaryQlClass() { result = "TypeAliasDeclaration" } @@ -548,6 +556,7 @@ class LocalNamespaceName extends @local_namespace_name, LexicalName { /** * Gets the canonical name of the namespace referenced by this name. */ + overlay[global] deprecated Namespace getNamespace() { result = this.getADeclaration().getNamespace() } override DeclarationSpace getDeclarationSpace() { result = "namespace" } @@ -568,6 +577,7 @@ class TypeExpr extends ExprOrType, @typeexpr, TypeAnnotation { * Has no result if this occurs in a TypeScript file that was extracted * without type information. */ + overlay[global] deprecated override Type getType() { ast_node_type(this, result) } override Stmt getEnclosingStmt() { result = ExprOrType.super.getEnclosingStmt() } @@ -692,6 +702,7 @@ class TypeAccess extends @typeaccess, TypeExpr, TypeRef { /** * Gets the canonical name of the type being accessed. */ + overlay[global] deprecated TypeName getTypeName() { ast_node_symbol(this, result) } override string getAPrimaryQlClass() { result = "TypeAccess" } @@ -1379,6 +1390,7 @@ class LocalNamespaceDecl extends VarDecl, NamespaceRef { /** * Gets the canonical name of the namespace being defined or aliased by this name. */ + overlay[global] deprecated Namespace getNamespace() { ast_node_symbol(this, result) } } @@ -1397,6 +1409,7 @@ class NamespaceAccess extends TypeExpr, NamespaceRef, @namespace_access { /** * Gets the canonical name of the namespace being accessed. */ + overlay[global] deprecated Namespace getNamespace() { ast_node_symbol(this, result) } override string getAPrimaryQlClass() { result = "NamespaceAccess" } @@ -1506,6 +1519,7 @@ class EnumDeclaration extends NamespaceDefinition, @enum_declaration, AST::Value /** * Gets the canonical name of the type being defined. */ + overlay[global] deprecated TypeName getTypeName() { ast_node_symbol(this, result) } /** @@ -1594,6 +1608,7 @@ class EnumMember extends AstNode, @enum_member { /** * Gets the canonical name of the type defined by this enum member. */ + overlay[global] deprecated TypeName getTypeName() { ast_node_symbol(this, result) } override string getAPrimaryQlClass() { result = "EnumMember" } @@ -1762,6 +1777,7 @@ class TypeRootFolder extends Folder { /** * Gets the priority with which this type root folder should be used from within the given search root. */ + overlay[global] int getSearchPriority(Folder searchRoot) { findNodeModulesFolder(searchRoot, this.getNodeModulesFolder(), result) } @@ -1780,6 +1796,7 @@ class TypeRootFolder extends Folder { * For instance, there may be many AST nodes representing different uses of the * `number` keyword, but there only exists one `number` type. */ +overlay[global] deprecated class Type extends @type { /** * Gets a string representation of this type. @@ -1984,6 +2001,7 @@ deprecated class Type extends @type { * * A union type or intersection type, such as `string | number` or `T & U`. */ +overlay[global] deprecated class UnionOrIntersectionType extends Type, @union_or_intersection_type { /** * Gets the `i`th member of this union or intersection, starting at 0. @@ -2012,6 +2030,7 @@ deprecated class UnionOrIntersectionType extends Type, @union_or_intersection_ty * Note that the `boolean` type is represented as the union `true | false`, * but is still displayed as `boolean` in string representations. */ +overlay[global] deprecated class UnionType extends UnionOrIntersectionType, @union_type { } /** @@ -2022,6 +2041,7 @@ deprecated class UnionType extends UnionOrIntersectionType, @union_type { } * * An intersection type, such as `T & {x: number}`. */ +overlay[global] deprecated class IntersectionType extends UnionOrIntersectionType, @intersection_type { } /** @@ -2040,6 +2060,7 @@ deprecated class IntersectionType extends UnionOrIntersectionType, @intersection * Foreign array-like objects such as `HTMLCollection` are not normal JavaScript arrays, * and their corresponding types are not considered array types either. */ +overlay[global] deprecated class ArrayType extends Type { ArrayType() { this instanceof @tuple_type or @@ -2061,6 +2082,7 @@ deprecated class ArrayType extends Type { * * An array type such as `Array`, or equivalently, `string[]`. */ +overlay[global] deprecated class PlainArrayType extends ArrayType, TypeReference { PlainArrayType() { this.hasQualifiedName("Array") } @@ -2075,6 +2097,7 @@ deprecated class PlainArrayType extends ArrayType, TypeReference { * * A read-only array type such as `ReadonlyArray`. */ +overlay[global] deprecated class ReadonlyArrayType extends ArrayType, TypeReference { ReadonlyArrayType() { this.hasQualifiedName("ReadonlyArray") } } @@ -2087,6 +2110,7 @@ deprecated class ReadonlyArrayType extends ArrayType, TypeReference { * * A tuple type, such as `[number, string]`. */ +overlay[global] deprecated class TupleType extends ArrayType, @tuple_type { /** * Gets the `i`th member of this tuple type, starting at 0. @@ -2148,6 +2172,7 @@ deprecated class TupleType extends ArrayType, @tuple_type { * * The predefined `any` type. */ +overlay[global] deprecated class AnyType extends Type, @any_type { } /** @@ -2158,6 +2183,7 @@ deprecated class AnyType extends Type, @any_type { } * * The predefined `unknown` type. */ +overlay[global] deprecated class UnknownType extends Type, @unknown_type { } /** @@ -2168,6 +2194,7 @@ deprecated class UnknownType extends Type, @unknown_type { } * * The predefined `string` type. */ +overlay[global] deprecated class StringType extends Type, @string_type { } /** @@ -2178,6 +2205,7 @@ deprecated class StringType extends Type, @string_type { } * * The predefined `number` type. */ +overlay[global] deprecated class NumberType extends Type, @number_type { } /** @@ -2188,6 +2216,7 @@ deprecated class NumberType extends Type, @number_type { } * * The predefined `bigint` type. */ +overlay[global] deprecated class BigIntType extends Type, @bigint_type { } /** @@ -2198,6 +2227,7 @@ deprecated class BigIntType extends Type, @bigint_type { } * * A boolean, number, or string literal type. */ +overlay[global] deprecated class LiteralType extends Type, @literal_type { /** * Gets the string value of this literal. @@ -2213,6 +2243,7 @@ deprecated class LiteralType extends Type, @literal_type { * * The boolean literal type `true` or `false`. */ +overlay[global] deprecated class BooleanLiteralType extends LiteralType, @boolean_literal_type { /** * Gets the boolean value represented by this type. @@ -2227,6 +2258,7 @@ deprecated class BooleanLiteralType extends LiteralType, @boolean_literal_type { /** * A number literal as a static type. */ +overlay[global] deprecated class NumberLiteralType extends LiteralType, @number_literal_type { override string getStringValue() { type_literal_value(this, result) } @@ -2249,6 +2281,7 @@ deprecated class NumberLiteralType extends LiteralType, @number_literal_type { * * A string literal as a static type. */ +overlay[global] deprecated class StringLiteralType extends LiteralType, @string_literal_type { override string getStringValue() { type_literal_value(this, result) } } @@ -2261,6 +2294,7 @@ deprecated class StringLiteralType extends LiteralType, @string_literal_type { * * A bigint literal as a static type. */ +overlay[global] deprecated class BigIntLiteralType extends LiteralType { override string getStringValue() { type_literal_value(this, result) } @@ -2283,6 +2317,7 @@ deprecated class BigIntLiteralType extends LiteralType { * * The `boolean` type, internally represented as the union type `true | false`. */ +overlay[global] deprecated class BooleanType extends UnionType { BooleanType() { this.getAnElementType() instanceof @true_type and @@ -2299,6 +2334,7 @@ deprecated class BooleanType extends UnionType { * * The `string` type or a string literal type. */ +overlay[global] deprecated class StringLikeType extends Type { StringLikeType() { this instanceof StringType or @@ -2314,6 +2350,7 @@ deprecated class StringLikeType extends Type { * * The `number` type or a number literal type. */ +overlay[global] deprecated class NumberLikeType extends Type { NumberLikeType() { this instanceof NumberType or @@ -2329,6 +2366,7 @@ deprecated class NumberLikeType extends Type { * * The `boolean`, `true,` or `false` type. */ +overlay[global] deprecated class BooleanLikeType extends Type { BooleanLikeType() { this instanceof BooleanType or @@ -2344,6 +2382,7 @@ deprecated class BooleanLikeType extends Type { * * The `void` type. */ +overlay[global] deprecated class VoidType extends Type, @void_type { } /** @@ -2354,6 +2393,7 @@ deprecated class VoidType extends Type, @void_type { } * * The `undefined` type. */ +overlay[global] deprecated class UndefinedType extends Type, @undefined_type { } /** @@ -2364,6 +2404,7 @@ deprecated class UndefinedType extends Type, @undefined_type { } * * The `null` type. */ +overlay[global] deprecated class NullType extends Type, @null_type { } /** @@ -2374,6 +2415,7 @@ deprecated class NullType extends Type, @null_type { } * * The `never` type. */ +overlay[global] deprecated class NeverType extends Type, @never_type { } /** @@ -2384,6 +2426,7 @@ deprecated class NeverType extends Type, @never_type { } * * The `symbol` type or a specific `unique symbol` type. */ +overlay[global] deprecated class SymbolType extends Type, @symbol_type { } /** @@ -2394,6 +2437,7 @@ deprecated class SymbolType extends Type, @symbol_type { } * * The `symbol` type. */ +overlay[global] deprecated class PlainSymbolType extends SymbolType, @plain_symbol_type { } /** @@ -2404,6 +2448,7 @@ deprecated class PlainSymbolType extends SymbolType, @plain_symbol_type { } * * A `unique symbol` type. */ +overlay[global] deprecated class UniqueSymbolType extends SymbolType, @unique_symbol_type { /** * Gets the canonical name of the variable exposing the symbol. @@ -2438,6 +2483,7 @@ deprecated class UniqueSymbolType extends SymbolType, @unique_symbol_type { * * The `object` type. */ +overlay[global] deprecated class ObjectKeywordType extends Type, @objectkeyword_type { } /** @@ -2448,6 +2494,7 @@ deprecated class ObjectKeywordType extends Type, @objectkeyword_type { } * * A type that refers to a class, interface, enum, or enum member. */ +overlay[global] deprecated class TypeReference extends Type, @type_reference { /** * Gets the canonical name of the type being referenced. @@ -2506,6 +2553,7 @@ deprecated class TypeReference extends Type, @type_reference { * * A type that refers to a class, possibly with type arguments. */ +overlay[global] deprecated class ClassType extends TypeReference { ClassDefinition declaration; @@ -2525,6 +2573,7 @@ deprecated class ClassType extends TypeReference { * * A type that refers to an interface, possibly with type arguents. */ +overlay[global] deprecated class InterfaceType extends TypeReference { InterfaceDeclaration declaration; @@ -2544,6 +2593,7 @@ deprecated class InterfaceType extends TypeReference { * * A type that refers to an enum. */ +overlay[global] deprecated class EnumType extends TypeReference { EnumDeclaration declaration; @@ -2563,6 +2613,7 @@ deprecated class EnumType extends TypeReference { * * A type that refers to the value of an enum member. */ +overlay[global] deprecated class EnumLiteralType extends TypeReference { EnumMember declaration; @@ -2582,6 +2633,7 @@ deprecated class EnumLiteralType extends TypeReference { * * A type that refers to a type alias. */ +overlay[global] deprecated class TypeAliasReference extends TypeReference { TypeAliasReference() { type_alias(this, _) } @@ -2601,6 +2653,7 @@ deprecated class TypeAliasReference extends TypeReference { * * An anonymous interface type, such as `{ x: number }`. */ +overlay[global] deprecated class AnonymousInterfaceType extends Type, @object_type { } /** @@ -2611,6 +2664,7 @@ deprecated class AnonymousInterfaceType extends Type, @object_type { } * * A type that refers to a type variable. */ +overlay[global] deprecated class TypeVariableType extends Type, @typevariable_type { /** * Gets a syntactic declaration of this type variable. @@ -2656,6 +2710,7 @@ deprecated class TypeVariableType extends Type, @typevariable_type { * * A type that refers to a type variable declared on a class, interface or function. */ +overlay[global] deprecated class CanonicalTypeVariableType extends TypeVariableType, @canonical_type_variable_type { override TypeName getHostType() { result = this.getCanonicalName().getParent() } @@ -2681,6 +2736,7 @@ deprecated class CanonicalTypeVariableType extends TypeVariableType, @canonical_ * - `(x: T) => T` * - `(x: S, y: T) => T`. */ +overlay[global] deprecated class LexicalTypeVariableType extends TypeVariableType, @lexical_type_variable_type { override string getName() { types(this, _, result) // The toString value contains the name. @@ -2703,6 +2759,7 @@ deprecated class LexicalTypeVariableType extends TypeVariableType, @lexical_type * } * ``` */ +overlay[global] deprecated class ThisType extends Type, @this_type { /** * Gets the type containing the `this` type. @@ -2721,6 +2778,7 @@ deprecated class ThisType extends Type, @this_type { * The type of a named value, `typeof X`, typically denoting the type of * a class constructor, namespace object, enum object, or module object. */ +overlay[global] deprecated class TypeofType extends Type, @typeof_type { /** * Gets the canonical name of the named value. @@ -2801,6 +2859,7 @@ module SignatureKind { * * A function or constructor signature in a TypeScript type. */ +overlay[global] deprecated class CallSignatureType extends @signature_type { /** * Gets a value indicating if this is a function or constructor signature. @@ -2955,6 +3014,7 @@ deprecated class CallSignatureType extends @signature_type { * * A function call signature in a type, that is, a signature without the `new` keyword. */ +overlay[global] deprecated class FunctionCallSignatureType extends CallSignatureType, @function_signature_type { } /** @@ -2965,6 +3025,7 @@ deprecated class FunctionCallSignatureType extends CallSignatureType, @function_ * * A constructor call signature in a type, that is, a signature with the `new` keyword. */ +overlay[global] deprecated class ConstructorCallSignatureType extends CallSignatureType, @constructor_signature_type { } @@ -2976,6 +3037,7 @@ deprecated class ConstructorCallSignatureType extends CallSignatureType, @constr * - It has one type parameter, say, `T` * - It has a `then` method whose first argument is a callback that takes a `T` as argument. */ +overlay[global] deprecated private class PromiseTypeName extends TypeName { PromiseTypeName() { // The name must suggest it is a promise. @@ -3005,6 +3067,7 @@ deprecated private class PromiseTypeName extends TypeName { * This includes types whose name and `then` method signature suggest it is a promise, * such as `PromiseLike` and `Thenable`. */ +overlay[global] deprecated class PromiseType extends TypeReference { PromiseType() { this.getNumTypeArgument() = 1 and diff --git a/javascript/ql/lib/semmle/javascript/Variables.qll b/javascript/ql/lib/semmle/javascript/Variables.qll index adc0ad5b9c87..5fa7473c3043 100644 --- a/javascript/ql/lib/semmle/javascript/Variables.qll +++ b/javascript/ql/lib/semmle/javascript/Variables.qll @@ -1,4 +1,6 @@ /** Provides classes for modeling program variables. */ +overlay[local] +module; import javascript @@ -62,6 +64,7 @@ class LocalScope extends Scope { */ class ModuleScope extends Scope, @module_scope { /** Gets the module that induces this scope. */ + overlay[global] Module getModule() { result = this.getScopeElement() } override string toString() { result = "module scope" } @@ -256,6 +259,7 @@ class VarRef extends @varref, Identifier, BindingPattern, LexicalRef { override VarRef getABindingVarRef() { result = this } + overlay[global] override predicate isImpure() { none() } override Expr getUnderlyingReference() { result = this } @@ -543,6 +547,7 @@ class ArrayPattern extends DestructuringPattern, @array_pattern { /** Holds if this array pattern has an omitted element. */ predicate hasOmittedElement() { this.elementIsOmitted(_) } + overlay[global] override predicate isImpure() { this.getAnElement().isImpure() } override VarRef getABindingVarRef() { @@ -583,6 +588,7 @@ class ObjectPattern extends DestructuringPattern, @object_pattern { /** Gets the rest property pattern of this object pattern, if any. */ override Expr getRest() { result = this.getChildExpr(-1) } + overlay[global] override predicate isImpure() { this.getAPropertyPattern().isImpure() } override VarRef getABindingVarRef() { @@ -640,6 +646,7 @@ class PropertyPattern extends @property, AstNode { ObjectPattern getObjectPattern() { properties(this, result, _, _, _) } /** Holds if this pattern is impure, that is, if its evaluation could have side effects. */ + overlay[global] predicate isImpure() { this.isComputed() and this.getNameExpr().isImpure() or @@ -844,6 +851,7 @@ class SimpleParameter extends Parameter, VarDecl { * Gets a use of this parameter that refers to its initial value as * passed in from the caller. */ + overlay[global] VarUse getAnInitialUse() { exists(SsaDefinition ssa | ssa.getAContributingVarDef() = this and diff --git a/javascript/ql/lib/semmle/javascript/XML.qll b/javascript/ql/lib/semmle/javascript/XML.qll index 54157809260b..ca401bd3f4be 100644 --- a/javascript/ql/lib/semmle/javascript/XML.qll +++ b/javascript/ql/lib/semmle/javascript/XML.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with XML files and their content. */ +overlay[local] +module; import semmle.files.FileSystem private import codeql.xml.Xml diff --git a/javascript/ql/lib/semmle/javascript/YAML.qll b/javascript/ql/lib/semmle/javascript/YAML.qll index a312d78b6fbe..01473226b44a 100644 --- a/javascript/ql/lib/semmle/javascript/YAML.qll +++ b/javascript/ql/lib/semmle/javascript/YAML.qll @@ -4,6 +4,8 @@ * YAML documents are represented as abstract syntax trees whose nodes * are either YAML values or alias nodes referring to another YAML value. */ +overlay[local] +module; import javascript private import codeql.yaml.Yaml as LibYaml diff --git a/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll b/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll index 41509516cc16..17908c0b67f1 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll @@ -37,6 +37,8 @@ * they represent; additionally, indefinite abstract values record * the source of imprecision that caused them to arise. */ +overlay[local] +module; private import javascript private import semmle.javascript.dataflow.internal.AbstractValuesImpl @@ -97,6 +99,7 @@ class AbstractValue extends TAbstractValue { * In all cases, purely local flow tracking is used to find prototype objects, so * this predicate cannot be relied on to compute all possible prototype objects. */ + overlay[global] DefiniteAbstractValue getAPrototype() { exists(AbstractProtoProperty proto | proto.getBase() = this and diff --git a/javascript/ql/lib/semmle/javascript/dataflow/AdditionalFlowSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/AdditionalFlowSteps.qll index d0deff8788ca..83d523e07094 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/AdditionalFlowSteps.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/AdditionalFlowSteps.qll @@ -33,21 +33,25 @@ private import semmle.javascript.internal.CachedStages * Note: For performance reasons, all subclasses of this class should be part * of the standard library. Use `isAdditionalFlowStep` for query-specific flow steps. */ +overlay[local] class AdditionalFlowStep extends Unit { /** * Holds if `pred` → `succ` should be considered a value-preserving data flow edge.f */ + overlay[global] predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() } /** * Holds if `pred` → `succ` should be considered a value-preserving data flow edge that * crosses calling contexts. */ + overlay[global] predicate jumpStep(DataFlow::Node pred, DataFlow::Node succ) { none() } /** * Holds if `pred` should be stored in the given `content` of the object `succ`. */ + overlay[global] predicate storeStep(DataFlow::Node pred, DataFlow::ContentSet contents, DataFlow::Node succ) { none() } @@ -55,6 +59,7 @@ class AdditionalFlowStep extends Unit { /** * Holds if the given `content` of the object in `pred` should be read into `succ`. */ + overlay[global] predicate readStep(DataFlow::Node pred, DataFlow::ContentSet contents, DataFlow::Node succ) { none() } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll index f773000c8cc3..3b4a6be84d03 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll @@ -625,15 +625,19 @@ abstract deprecated class LabeledBarrierGuardNode extends BarrierGuardNode { * * For use with load/store steps in `DataFlow::SharedFlowStep` and TypeTracking. */ +overlay[local] module PseudoProperties { /** Holds if `s` is a pseudo-property. */ bindingset[s] + overlay[caller] predicate isPseudoProperty(string s) { s.matches("$%$") } bindingset[s] + overlay[caller] private string pseudoProperty(string s) { result = "$" + s + "$" } bindingset[s, v] + overlay[caller] private string pseudoProperty(string s, string v) { result = "$" + s + "|" + v + "$" } /** @@ -680,6 +684,7 @@ module PseudoProperties { * Gets a pseudo-property for the location of a map value where the key is `key`. * The string value of the `key` is encoded in the result, and there is only a result if the string value of `key` is known. */ + overlay[caller] pragma[inline] string mapValueKnownKey(DataFlow::Node key) { result = mapValueKey(any(string s | key.mayHaveStringValue(s))) @@ -689,17 +694,20 @@ module PseudoProperties { * Gets a pseudo-property for the location of a map value where the key is `key`. */ bindingset[key] + overlay[caller] string mapValueKey(string key) { result = pseudoProperty("mapValue", key) } /** * Holds if `prop` equals `mapValueKey(key)` for some value of `key`. */ bindingset[prop] + overlay[caller] predicate isMapValueKey(string prop) { prop.matches("$mapValue|%$") } /** * Gets a pseudo-property for the location of a map value where the key is `key`. */ + overlay[caller] pragma[inline] string mapValue(DataFlow::Node key) { result = mapValueKnownKey(key) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll b/javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll index 5a762f4aa1bb..3c12284d77b5 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll @@ -7,6 +7,8 @@ * For performance reasons, all subclasses of `CustomAbstractValueDefinition` * should be part of the standard library. */ +overlay[local] +module; private import javascript private import internal.AbstractValuesImpl @@ -32,6 +34,7 @@ class CustomAbstractValueFromDefinition extends AbstractValue, TCustomAbstractVa override predicate isIndefinite(DataFlow::Incompleteness cause) { def.isIndefinite(cause) } + overlay[global] override DefiniteAbstractValue getAPrototype() { result = def.getAPrototype() } override predicate hasLocationInfo( @@ -98,6 +101,7 @@ abstract class CustomAbstractValueDefinition extends Locatable { * Gets an abstract value that represents a prototype object of the * induced abstract value. */ + overlay[global] AbstractValue getAPrototype() { exists(AbstractProtoProperty proto | proto.getBase() = this.getAbstractValue() and @@ -119,6 +123,7 @@ abstract class CustomAbstractValueDefinition extends Locatable { /** * Flow analysis for custom abstract values. */ +overlay[global] class CustomAbstractValueFromDefinitionNode extends DataFlow::AnalyzedNode, DataFlow::ValueNode { CustomAbstractValueFromDefinition val; diff --git a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll index 071d6d084333..a61b67e643fe 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll @@ -17,6 +17,8 @@ * Flow through global variables, object properties or function calls is not * modeled (except for immediately invoked functions as explained above). */ +overlay[local] +module; import javascript private import internal.CallGraphs @@ -64,9 +66,11 @@ module DataFlow { * `p.getALocalSource()` does _not_ return the corresponding argument, and * `p.isIncomplete("call")` holds. */ + overlay[global] predicate isIncomplete(Incompleteness cause) { isIncomplete(this, cause) } /** Gets type inference results for this data flow node. */ + overlay[global] AnalyzedNode analyze() { result = this } /** Gets the expression corresponding to this data flow node, if any. */ @@ -98,6 +102,7 @@ module DataFlow { * Holds if this data flow node accesses the global variable `g`, either directly * or through the `window` object. */ + overlay[global] predicate accessesGlobal(string g) { globalVarRef(g).flowsTo(this) } /** Holds if this node may evaluate to the string `s`, possibly through local data flow. */ @@ -124,11 +129,13 @@ module DataFlow { int getIntValue() { result = this.asExpr().getIntValue() } /** Gets a function value that may reach this node. */ + overlay[global] final FunctionNode getAFunctionValue() { CallGraph::getAFunctionReference(result, 0).flowsTo(this) } /** Gets a function value that may reach this node with the given `imprecision` level. */ + overlay[global] final FunctionNode getAFunctionValue(int imprecision) { CallGraph::getAFunctionReference(result, imprecision).flowsTo(this) } @@ -137,6 +144,7 @@ module DataFlow { * Gets a function value that may reach this node, * possibly derived from a partial function invocation. */ + overlay[global] final FunctionNode getABoundFunctionValue(int boundArgs) { result = this.getAFunctionValue() and boundArgs = 0 or @@ -192,6 +200,7 @@ module DataFlow { FlowSteps::identityFunctionStep(result, this) } + overlay[global] private NameResolution::Node getNameResolutionNode() { this = valueNode(result) or @@ -205,6 +214,7 @@ module DataFlow { * Holds if this node is annotated with the given named type, * or is declared as a subtype thereof, or is a union or intersection containing such a type. */ + overlay[global] cached predicate hasUnderlyingType(string globalName) { Stages::TypeTracking::ref() and @@ -218,6 +228,7 @@ module DataFlow { * Holds if this node is annotated with the given named type, * or is declared as a subtype thereof, or is a union or intersection containing such a type. */ + overlay[global] cached predicate hasUnderlyingType(string moduleName, string typeName) { Stages::TypeTracking::ref() and @@ -466,6 +477,7 @@ module DataFlow { /** * Gets an accessor (`get` or `set` method) that may be invoked by this property reference. */ + overlay[global] final DataFlow::FunctionNode getAnAccessorCallee() { result = CallGraph::getAnAccessorCallee(this) } @@ -1762,6 +1774,7 @@ module DataFlow { ) } + overlay[global] private class ReflectiveParamsStep extends LegacyPreCallGraphStep { override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) { exists(DataFlow::ReflectiveParametersNode params, DataFlow::FunctionNode f, int i | @@ -1774,6 +1787,7 @@ module DataFlow { } /** A taint step from the reflective parameters node to any parameter. */ + overlay[global] private class ReflectiveParamsTaintStep extends TaintTracking::LegacyTaintStep { override predicate step(DataFlow::Node obj, DataFlow::Node element) { exists(DataFlow::ReflectiveParametersNode params, DataFlow::FunctionNode f | @@ -1787,6 +1801,7 @@ module DataFlow { /** * Holds if there is a step from `pred` to `succ` through a field accessed through `this` in a class. */ + overlay[global] predicate localFieldStep(DataFlow::Node pred, DataFlow::Node succ) { exists(ClassNode cls, string prop | pred = AccessPath::getAnAssignmentTo(cls.getADirectSuperClass*().getAReceiverNode(), prop) or @@ -1819,6 +1834,7 @@ module DataFlow { * `p.getALocalSource()` does _not_ return the corresponding argument, and * `p.isIncomplete("call")` holds. */ + overlay[global] predicate isIncomplete(Node nd, Incompleteness cause) { exists(SsaVariable ssa | nd = TSsaDefNode(ssa.getDefinition()) | defIsIncomplete(ssa.(SsaExplicitDefinition).getDef(), cause) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll b/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll index eb7160683a76..13aa5628111c 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll @@ -1,4 +1,6 @@ /** Provides classes and predicates for defining flow summaries. */ +overlay[local] +module; private import javascript private import semmle.javascript.dataflow.internal.sharedlib.FlowSummaryImpl as Impl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll b/javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll index b7b2b9ba1e5b..48c21d41d75d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + /** * Types inferred by the flow analysis, represented as type tags. * diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll index 0e6394a6f557..c4c7b1d7d18a 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll @@ -3,6 +3,8 @@ * as nodes corresponding to function definitions or nodes corresponding to * parameters. */ +overlay[local] +module; private import javascript private import semmle.javascript.dependencies.Dependencies @@ -158,6 +160,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * addEventHandler("click", foo.bind(this, "value of x")) * ``` */ + overlay[global] ParameterNode getABoundCallbackParameter(int callback, int param) { exists(int boundArgs | result = @@ -178,6 +181,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN private ObjectLiteralNode getOptionsArgument(int i) { result.flowsTo(this.getArgument(i)) } /** Gets an abstract value representing possible callees of this call site. */ + overlay[global] final AbstractValue getACalleeValue() { exists(DataFlow::Node callee, DataFlow::AnalyzedNode analyzed | pragma[only_bind_into](callee) = this.getCalleeNode() and @@ -192,6 +196,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * To alter the call graph as seen by the interprocedural data flow libraries, override * the `getACallee(int imprecision)` predicate instead. */ + overlay[global] final Function getACallee() { result = this.getACallee(0) } /** @@ -206,6 +211,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * This predicate can be overridden to alter the call graph used by the interprocedural * data flow libraries. */ + overlay[global] Function getACallee(int imprecision) { result = CallGraph::getACallee(this, imprecision).getFunction() } @@ -214,6 +220,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * Holds if the approximation of possible callees for this call site is * affected by the given analysis incompleteness `cause`. */ + overlay[global] predicate isIndefinite(DataFlow::Incompleteness cause) { this.getACalleeValue().isIndefinite(cause) } @@ -229,6 +236,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * independent contexts, so tracking flow through it leads to * imprecision. */ + overlay[global] predicate isImprecise() { this.isIndefinite("global") and exists(DefiniteAbstractValue v | v = this.getACalleeValue() | not v instanceof AbstractCallable) @@ -238,6 +246,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * Holds if our approximation of possible callees for this call site is * likely to be incomplete. */ + overlay[global] predicate isIncomplete() { // the flow analysis identifies a source of incompleteness other than // global flow (which usually leads to imprecision rather than incompleteness) @@ -248,6 +257,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * Holds if our approximation of possible callees for this call site is * likely to be imprecise or incomplete. */ + overlay[global] predicate isUncertain() { this.isImprecise() or this.isIncomplete() } /** @@ -763,7 +773,7 @@ module ModuleImportNode { cached ModuleImportNode moduleImport(string path) { // NB. internal modules may be imported with a "node:" prefix - Stages::Imports::ref() and result.getPath() = ["node:" + path, path] + result.getPath() = ["node:" + path, path] } /** @@ -771,6 +781,7 @@ ModuleImportNode moduleImport(string path) { * `require("lodash")` in a context where a package.json file includes * `"lodash"` as a dependency. */ +overlay[global] ModuleImportNode dependencyModuleImport(Dependency dep) { result = dep.getAUse("import").(Import).getImportedModuleNode() } @@ -780,6 +791,7 @@ ModuleImportNode dependencyModuleImport(Dependency dep) { * the given `path`, or accesses `m` as a member on a default or * namespace import from `path`. */ +overlay[global] DataFlow::SourceNode moduleMember(string path, string m) { result = moduleImport(path).getAPropertyRead(m) } @@ -861,6 +873,7 @@ module MemberKind { * * Additional patterns can be recognized as class nodes, by extending `DataFlow::ClassNode::Range`. */ +overlay[global] class ClassNode extends DataFlow::ValueNode, DataFlow::SourceNode { override AST::ValueNode astNode; AbstractCallable function; @@ -1329,6 +1342,7 @@ class ClassNode extends DataFlow::ValueNode, DataFlow::SourceNode { /** * Helper predicate to get a prototype reference in a file. */ +overlay[global] private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) { result.getBase() = AccessPath::getAReferenceOrAssignmentTo(name) and result.getPropertyName() = "prototype" and @@ -1338,6 +1352,7 @@ private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) { /** * Helper predicate to get an instantiation in a file. */ +overlay[global] private DataFlow::NewNode getAnInstantiationInFile(string name, File f) { result = AccessPath::getAReferenceTo(name).(DataFlow::LocalSourceNode).getAnInstantiation() and result.getFile() = f @@ -1346,6 +1361,7 @@ private DataFlow::NewNode getAnInstantiationInFile(string name, File f) { /** * Gets a reference to the function `func`, where there exists a read/write of the "prototype" property on that reference. */ +overlay[global] pragma[noinline] private DataFlow::SourceNode getAFunctionValueWithPrototype(AbstractValue func) { exists(result.getAPropertyReference("prototype")) and @@ -1353,6 +1369,7 @@ private DataFlow::SourceNode getAFunctionValueWithPrototype(AbstractValue func) func instanceof AbstractCallable // the join-order goes bad if `func` has type `AbstractFunction`. } +overlay[global] module ClassNode { /** * A dataflow node that should be considered a class node. @@ -1435,6 +1452,7 @@ module ClassNode { * _.partial(fn, x, y, z) * ``` */ +overlay[global] class PartialInvokeNode extends DataFlow::Node instanceof PartialInvokeNode::Range { /** Gets a node holding a callback invoked by this partial invocation node. */ DataFlow::Node getACallbackNode() { @@ -1470,6 +1488,7 @@ class PartialInvokeNode extends DataFlow::Node instanceof PartialInvokeNode::Ran } } +overlay[global] module PartialInvokeNode { /** * A data flow node that performs a partial function application. @@ -1717,6 +1736,7 @@ class RegExpCreationNode extends DataFlow::SourceNode { predicate maybeGlobal() { RegExp::maybeGlobal(this.tryGetFlags()) } /** Gets a data flow node referring to this regular expression. */ + overlay[global] private DataFlow::SourceNode getAReference(DataFlow::TypeTracker t) { t.start() and result = this @@ -1725,6 +1745,7 @@ class RegExpCreationNode extends DataFlow::SourceNode { } /** Gets a data flow node referring to this regular expression. */ + overlay[global] cached DataFlow::SourceNode getAReference() { Stages::FlowSteps::ref() and @@ -1736,6 +1757,7 @@ class RegExpCreationNode extends DataFlow::SourceNode { * A guard node for a variable in a negative condition, such as `x` in `if(!x)`. * Can be added to a `isBarrier` in a data-flow configuration to block flow through such checks. */ +overlay[global] class VarAccessBarrier extends DataFlow::Node { VarAccessBarrier() { exists(ConditionGuardNode guard, SsaRefinementNode refinement | diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll b/javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll index feb0187487e5..b1302df6fbc7 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll @@ -27,6 +27,8 @@ * so the refinement can evaluate to both `true` and `false` for the same * candidate value. */ +overlay[local] +module; import javascript private import AbstractValues @@ -45,6 +47,7 @@ abstract class RefinementCandidate extends Expr { /** * Gets a refinement value inferred for this expression in context `ctxt`. */ + overlay[global] pragma[nomagic] abstract RefinementValue eval(RefinementContext ctxt); } @@ -64,6 +67,7 @@ class Refinement extends Expr instanceof RefinementCandidate { /** * Gets a refinement value inferred for this expression in context `ctxt`. */ + overlay[global] RefinementValue eval(RefinementContext ctxt) { result = super.eval(ctxt) } } @@ -71,6 +75,7 @@ class Refinement extends Expr instanceof RefinementCandidate { abstract private class LiteralRefinement extends RefinementCandidate, Literal { override SsaSourceVariable getARefinedVar() { none() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { ctxt.appliesTo(this) and result = this.eval() } @@ -78,16 +83,19 @@ abstract private class LiteralRefinement extends RefinementCandidate, Literal { /** * Gets the refinement value that represents this literal. */ + overlay[global] RefinementValue eval() { result = TAny() } } /** A `null` literal, viewed as a refinement expression. */ private class NullLiteralRefinement extends LiteralRefinement, NullLiteral { + overlay[global] override RefinementValue eval() { result = TValueWithType(TTNull()) } } /** A Boolean literal, viewed as a refinement expression. */ private class BoolRefinement extends LiteralRefinement, BooleanLiteral { + overlay[global] override RefinementValue eval() { exists(boolean b | b.toString() = this.getValue() | result = TBoolConstant(b)) } @@ -95,11 +103,13 @@ private class BoolRefinement extends LiteralRefinement, BooleanLiteral { /** A constant string, viewed as a refinement expression. */ private class StringRefinement extends LiteralRefinement, ConstantString { + overlay[global] override RefinementValue eval() { result = TStringConstant(this.getStringValue()) } } /** A numeric literal, viewed as a refinement expression. */ abstract private class NumberRefinement extends LiteralRefinement, NumberLiteral { + overlay[global] override RefinementValue eval() { result = TValueWithType(TTNumber()) } } @@ -112,6 +122,7 @@ abstract private class NumberRefinement extends LiteralRefinement, NumberLiteral private class IntRefinement extends NumberRefinement, NumberLiteral { IntRefinement() { this.getValue().toInt() = 0 } + overlay[global] override RefinementValue eval() { result = TIntConstant(this.getValue().toInt()) } } @@ -123,6 +134,7 @@ private class UndefinedInRefinement extends RefinementCandidate, { override SsaSourceVariable getARefinedVar() { none() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { ctxt.appliesTo(this) and result = TValueWithType(TTUndefined()) @@ -135,6 +147,7 @@ private class VariableRefinement extends RefinementCandidate, VarUse { override SsaSourceVariable getARefinedVar() { result = this.getVariable() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { ctxt.appliesTo(this) and result = ctxt.(VarRefinementContext).getAValue() @@ -149,6 +162,7 @@ private class ParRefinement extends RefinementCandidate, ParExpr { result = this.getExpression().(RefinementCandidate).getARefinedVar() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { result = this.getExpression().(RefinementCandidate).eval(ctxt) } @@ -162,6 +176,7 @@ private class TypeofRefinement extends RefinementCandidate, TypeofExpr { result = this.getOperand().(RefinementCandidate).getARefinedVar() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { exists(RefinementValue opVal | opVal = this.getOperand().(RefinementCandidate).eval(ctxt) and @@ -182,6 +197,7 @@ private class EqRefinement extends RefinementCandidate, EqualityTest { result = this.getRightOperand().(RefinementCandidate).getARefinedVar() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { exists(RefinementCandidate l, RefinementValue lv, RefinementCandidate r, RefinementValue rv | l = this.getLeftOperand() and @@ -220,6 +236,7 @@ private class IndexRefinement extends RefinementCandidate, IndexExpr { result = this.getIndex().(RefinementCandidate).getARefinedVar() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { exists( RefinementCandidate base, RefinementValue baseVal, RefinementCandidate index, @@ -242,6 +259,7 @@ private class IndexRefinement extends RefinementCandidate, IndexExpr { * if any. */ bindingset[s, i] +overlay[global] private RefinementValue evalIndex(StringConstant s, IntConstant i) { result = TStringConstant(s.getValue().charAt(i.getValue())) } @@ -249,6 +267,7 @@ private RefinementValue evalIndex(StringConstant s, IntConstant i) { /** * A context in which a refinement expression is analyzed. */ +overlay[global] newtype TRefinementContext = /** * A refinement context associated with refinement `ref`, specifying that variable `var` @@ -266,6 +285,7 @@ newtype TRefinementContext = /** * A context in which a refinement expression is analyzed. */ +overlay[global] class RefinementContext extends TRefinementContext { /** * Holds if refinement expression `cand` might be analyzed in this context. @@ -280,6 +300,7 @@ class RefinementContext extends TRefinementContext { * A refinement context specifying that some variable is assumed to have one particular * abstract value. */ +overlay[global] class VarRefinementContext extends RefinementContext, TVarRefinementContext { override predicate appliesTo(RefinementCandidate cand) { exists(AnalyzedRefinement ref, SsaSourceVariable var | diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll b/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll index 7503e5001e0f..85a8a163cba4 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll @@ -5,6 +5,8 @@ * Note that unlike `TypeTracking.qll`, this library only performs * local tracking within a function. */ +overlay[local] +module; private import javascript private import semmle.javascript.dataflow.TypeTracking @@ -192,6 +194,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range { * * See `TypeTracker` for more details about how to use this. */ + overlay[global] pragma[inline] DataFlow::SourceNode track(TypeTracker t2, TypeTracker t) { t = t2.step(this, result) } @@ -200,6 +203,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range { * * See `TypeBackTracker` for more details about how to use this. */ + overlay[global] pragma[inline] DataFlow::SourceNode backtrack(TypeBackTracker t2, TypeBackTracker t) { t2 = t.step(result, this) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll index 6bcef1dc4128..97daed1f30a6 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll @@ -3,6 +3,8 @@ * * Provides a representation for abstract values. */ +overlay[local] +module; private import javascript import semmle.javascript.dataflow.AbstractValues diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll index 3bcc36a65773..b7538c7ffbf0 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll @@ -14,6 +14,8 @@ * to the same value have the same access paths, so access paths are neither sound nor * complete as an approximation of expression semantics. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AdditionalFlowInternal.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AdditionalFlowInternal.qll index d7f92ce8dd30..dfa924699ba5 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AdditionalFlowInternal.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AdditionalFlowInternal.qll @@ -5,6 +5,7 @@ private import semmle.javascript.dataflow.internal.DataFlowPrivate /** * Gets a data-flow node synthesized using `AdditionalFlowInternal#needsSynthesizedNode`. */ +overlay[local] DataFlow::Node getSynthesizedNode(AstNode node, string tag) { result = TGenericSynthesizedNode(node, tag, _) } @@ -12,6 +13,7 @@ DataFlow::Node getSynthesizedNode(AstNode node, string tag) { /** * An extension to `AdditionalFlowStep` with additional internal-only predicates. */ +overlay[local] class AdditionalFlowInternal extends DataFlow::AdditionalFlowStep { /** * Holds if a data-flow node should be synthesized for the pair `(node, tag)`. @@ -25,10 +27,12 @@ class AdditionalFlowInternal extends DataFlow::AdditionalFlowStep { /** * Holds if `node` should only permit flow of values stored in `contents`. */ + overlay[global] predicate expectsContent(DataFlow::Node node, DataFlow::ContentSet contents) { none() } /** * Holds if `node` should not permit flow of values stored in `contents`. */ + overlay[global] predicate clearsContent(DataFlow::Node node, DataFlow::ContentSet contents) { none() } } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll index a5af2737c186..be9bc2c81a3d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import javascript private import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels private import semmle.javascript.dataflow.internal.FlowSummaryPrivate as FlowSummaryPrivate @@ -333,12 +336,14 @@ module Public { /** * A content set containing only the given content. */ + overlay[caller] pragma[inline] ContentSet singleton(Content content) { result.asSingleton() = content } /** * A content set corresponding to the given property name. */ + overlay[caller] pragma[inline] ContentSet property(PropertyName name) { result.asSingleton().asPropertyName() = name } @@ -399,6 +404,7 @@ module Public { * If `bound` is too large, it is truncated to the greatest lower bound we can represent. */ bindingset[bound] + overlay[caller] ContentSet arrayElementLowerBoundFromInt(int bound) { result = arrayElementLowerBound(bound.minimum(getMaxPreciseArrayIndex() + 1)) } @@ -409,6 +415,7 @@ module Public { * If `n` is too large, it is truncated to the greatest lower bound we can represent. */ bindingset[n] + overlay[caller] ContentSet arrayElementFromInt(int n) { result = arrayElementKnown(n) or @@ -448,6 +455,7 @@ module Public { * If `key` is not one of the keys we track precisely, this is mapped to the unknown key instead. */ bindingset[key] + overlay[caller] ContentSet mapValueFromKey(string key) { result = mapValueWithKnownKey(key) or @@ -510,6 +518,7 @@ module Public { * are mapped to their corresponding content sets (which are no longer seen as property names). */ bindingset[propertyName] + overlay[caller] ContentSet fromLegacyProperty(string propertyName) { result = fromLegacyPseudoProperty(propertyName) or diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll index 8d54f639cb0a..4a354e1f7593 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll @@ -3,6 +3,8 @@ * * Contains the raw data type underlying `DataFlow::Node`. */ +overlay[local] +module; private import javascript private import codeql.util.Boolean diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll index 1a4051ccdf66..68cf0aa4287b 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import javascript private import semmle.javascript.dataflow.internal.CallGraphs private import semmle.javascript.dataflow.internal.DataFlowNode @@ -310,6 +313,7 @@ private predicate returnNodeImpl(DataFlow::Node node, ReturnKind kind) { kind = MkExceptionalReturnKind() } +overlay[global] private DataFlow::Node getAnOutNodeImpl(DataFlowCall call, ReturnKind kind) { kind = MkNormalReturnKind() and result = call.asOrdinaryCall() or @@ -336,10 +340,12 @@ class ReturnNode extends DataFlow::Node { } /** A node that receives an output from a call. */ +overlay[global] class OutNode extends DataFlow::Node { OutNode() { this = getAnOutNodeImpl(_, _) } } +overlay[global] OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { result = getAnOutNodeImpl(call, kind) } cached @@ -416,9 +422,11 @@ abstract class LibraryCallable extends string { LibraryCallable() { any() } /** Gets a call to this library callable. */ + overlay[global] DataFlow::InvokeNode getACall() { none() } /** Same as `getACall()` except this does not depend on the call graph or API graph. */ + overlay[global] DataFlow::InvokeNode getACallSimple() { none() } } @@ -432,6 +440,7 @@ abstract class LibraryCallableInternal extends LibraryCallable { * * Same as `getACall()` but is evaluated later and may depend negatively on `getACall()`. */ + overlay[global] DataFlow::InvokeNode getACallStage2() { none() } } @@ -467,6 +476,7 @@ predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition isParameterNodeImpl(p, c, pos) } +overlay[global] private predicate isArgumentNodeImpl(Node n, DataFlowCall call, ArgumentPosition pos) { n = call.asOrdinaryCall().getArgument(pos.asPositional()) or @@ -523,6 +533,7 @@ private predicate isArgumentNodeImpl(Node n, DataFlowCall call, ArgumentPosition ) } +overlay[global] predicate isArgumentNode(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) { isArgumentNodeImpl(n, call, pos) } @@ -545,11 +556,13 @@ DataFlowCallable nodeGetEnclosingCallable(Node node) { node instanceof DataFlow::XmlAttributeNode and result.asFileCallable() = node.getFile() } +overlay[global] newtype TDataFlowType = TFunctionType(Function f) or TInstanceType(DataFlow::ClassNode cls) or TAnyType() +overlay[global] class DataFlowType extends TDataFlowType { string toDebugString() { result = @@ -575,6 +588,7 @@ class DataFlowType extends TDataFlowType { /** * Holds if `t1` is strictly stronger than `t2`. */ +overlay[global] predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { // 't1' is a subclass of 't2' t1.asInstanceOfClass() = t2.asInstanceOfClass().getADirectSubClass+() @@ -584,6 +598,7 @@ predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { t2 = TAnyType() } +overlay[global] private DataFlowType getPreciseType(Node node) { exists(Function f | (node = TValueNode(f) or node = TFunctionSelfReferenceNode(f)) and @@ -598,6 +613,7 @@ private DataFlowType getPreciseType(Node node) { result = getPreciseType(node.(PostUpdateNode).getPreUpdateNode()) } +overlay[global] DataFlowType getNodeType(Node node) { result = getPreciseType(node) or @@ -681,19 +697,23 @@ predicate neverSkipInPathGraph(Node node) { node.asExpr() instanceof VarRef } +overlay[global] string ppReprType(DataFlowType t) { none() } +overlay[global] pragma[inline] private predicate compatibleTypesWithAny(DataFlowType t1, DataFlowType t2) { t1 != TAnyType() and t2 = TAnyType() } +overlay[global] pragma[nomagic] private predicate compatibleTypes1(DataFlowType t1, DataFlowType t2) { t1.asInstanceOfClass().getADirectSubClass+() = t2.asInstanceOfClass() } +overlay[global] pragma[inline] predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { t1 = t2 @@ -767,6 +787,7 @@ ContentApprox getContentApprox(Content c) { c instanceof MkCapturedContent and result = TApproxCapturedContent() } +overlay[global] cached private newtype TDataFlowCall = MkOrdinaryCall(DataFlow::InvokeNode node) or @@ -791,6 +812,7 @@ private newtype TDataFlowCall = FlowSummaryImpl::Private::summaryCallbackRange(c, receiver) } +overlay[global] class DataFlowCall extends TDataFlowCall { DataFlowCallable getEnclosingCallable() { none() } // Overridden in subclass @@ -816,6 +838,7 @@ class DataFlowCall extends TDataFlowCall { Location getLocation() { none() } // Overridden in subclass } +overlay[global] private class OrdinaryCall extends DataFlowCall, MkOrdinaryCall { private DataFlow::InvokeNode node; @@ -832,6 +855,7 @@ private class OrdinaryCall extends DataFlowCall, MkOrdinaryCall { override Location getLocation() { result = node.getLocation() } } +overlay[global] private class PartialCall extends DataFlowCall, MkPartialCall { private DataFlow::PartialInvokeNode node; private DataFlow::Node callback; @@ -851,6 +875,7 @@ private class PartialCall extends DataFlowCall, MkPartialCall { override Location getLocation() { result = node.getLocation() } } +overlay[global] private class BoundCall extends DataFlowCall, MkBoundCall { private DataFlow::InvokeNode node; private int boundArgs; @@ -868,6 +893,7 @@ private class BoundCall extends DataFlowCall, MkBoundCall { override Location getLocation() { result = node.getLocation() } } +overlay[global] private class AccessorCall extends DataFlowCall, MkAccessorCall { private DataFlow::PropRef ref; @@ -882,6 +908,7 @@ private class AccessorCall extends DataFlowCall, MkAccessorCall { override Location getLocation() { result = ref.getLocation() } } +overlay[global] class SummaryCall extends DataFlowCall, MkSummaryCall { private FlowSummaryImpl::Public::SummarizedCallable enclosingCallable; private FlowSummaryImpl::Private::SummaryNode receiver; @@ -908,6 +935,7 @@ class SummaryCall extends DataFlowCall, MkSummaryCall { * This is to help ensure captured variables can flow into the lambda in cases where * we can't find its call sites. */ +overlay[global] private class ImpliedLambdaCall extends DataFlowCall, MkImpliedLambdaCall { private Function function; @@ -981,6 +1009,7 @@ class DataFlowExpr = Expr; Node exprNode(DataFlowExpr expr) { result = DataFlow::exprNode(expr) } +overlay[global] pragma[nomagic] predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos @@ -993,6 +1022,7 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { // are only using these in cases where either the call or callee is generated by a flow summary. } +overlay[global] pragma[inline] DataFlowCallable viableCallable(DataFlowCall node) { // Note: we never include call edges externs here, as it negatively affects the field-flow branch limit, @@ -1021,6 +1051,7 @@ DataFlowCallable viableCallable(DataFlowCall node) { result.asSourceCallableNotExterns() = node.asImpliedLambdaCall() } +overlay[global] private DataFlowCall getACallOnThis(DataFlow::ClassNode cls) { result.asOrdinaryCall() = cls.getAReceiverNode().getAPropertyRead().getACall() or @@ -1029,6 +1060,7 @@ private DataFlowCall getACallOnThis(DataFlow::ClassNode cls) { result.asPartialCall().getACallbackNode() = cls.getAReceiverNode().getAPropertyRead() } +overlay[global] private predicate downwardCall(DataFlowCall call) { exists(DataFlow::ClassNode cls | call = getACallOnThis(cls) and @@ -1041,9 +1073,11 @@ private predicate downwardCall(DataFlowCall call) { * Holds if the set of viable implementations that can be called by `call` * might be improved by knowing the call context. */ +overlay[global] predicate mayBenefitFromCallContext(DataFlowCall call) { downwardCall(call) } /** Gets the type of the receiver of `call`. */ +overlay[global] private DataFlowType getThisArgumentType(DataFlowCall call) { exists(DataFlow::Node node | isArgumentNodeImpl(node, call, MkThisParameter()) and @@ -1052,6 +1086,7 @@ private DataFlowType getThisArgumentType(DataFlowCall call) { } /** Gets the type of the 'this' parameter of `call`. */ +overlay[global] private DataFlowType getThisParameterType(DataFlowCallable callable) { exists(DataFlow::Node node | isParameterNodeImpl(node, callable, MkThisParameter()) and @@ -1063,6 +1098,7 @@ private DataFlowType getThisParameterType(DataFlowCallable callable) { * Gets a viable dispatch target of `call` in the context `ctx`. This is * restricted to those `call`s for which a context might make a difference. */ +overlay[global] DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { mayBenefitFromCallContext(call) and result = viableCallable(call) and @@ -1071,16 +1107,19 @@ DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { } bindingset[node, fun] +overlay[caller] pragma[inline_late] private predicate sameContainerAsEnclosingContainer(Node node, Function fun) { node.getContainer() = fun.getEnclosingContainer() } +overlay[global] abstract private class BarrierGuardAdapter extends DataFlow::Node { // Note: avoid depending on DataFlow::FlowLabel here as it will cause these barriers to be re-evaluated predicate blocksExpr(boolean outcome, Expr e) { none() } } +overlay[global] deprecated private class BarrierGuardAdapterSubclass extends BarrierGuardAdapter instanceof DataFlow::AdditionalBarrierGuardNode { override predicate blocksExpr(boolean outcome, Expr e) { super.blocks(outcome, e) } @@ -1092,6 +1131,7 @@ deprecated private class BarrierGuardAdapterSubclass extends BarrierGuardAdapter * * The standard library contains no subclasses of that class; this is for backwards compatibility only. */ +overlay[global] pragma[nomagic] private predicate legacyBarrier(DataFlow::Node node) { node = MakeBarrierGuard::getABarrierNode() @@ -1100,6 +1140,7 @@ private predicate legacyBarrier(DataFlow::Node node) { /** * Holds if `node` should be removed from the local data flow graph, for compatibility with legacy code. */ +overlay[global] pragma[nomagic] private predicate isBlockedLegacyNode(Node node) { // Ignore captured variable nodes for those variables that are handled by the captured-variable library. @@ -1155,6 +1196,7 @@ private predicate imprecisePostUpdateStep(DataFlow::PostUpdateNode postUpdate, D * Holds if there is a value-preserving steps `node1` -> `node2` that might * be cross function boundaries. */ +overlay[global] private predicate valuePreservingStep(Node node1, Node node2) { node1.getASuccessor() = node2 and not isBlockedLegacyNode(node1) and @@ -1223,10 +1265,12 @@ private predicate useUseFlow(Node node1, Node node2) { ) } +overlay[global] predicate simpleLocalFlowStep(Node node1, Node node2, string model) { simpleLocalFlowStep(node1, node2) and model = "" } +overlay[global] predicate simpleLocalFlowStep(Node node1, Node node2) { valuePreservingStep(node1, node2) and nodeGetEnclosingCallable(pragma[only_bind_out](node1)) = @@ -1314,6 +1358,7 @@ private predicate excludedJumpStep(Node node1, Node node2) { * that does not follow a call edge. For example, a step through a global * variable. */ +overlay[global] predicate jumpStep(Node node1, Node node2) { valuePreservingStep(node1, node2) and node1.getContainer() != node2.getContainer() and @@ -1330,6 +1375,7 @@ predicate jumpStep(Node node1, Node node2) { * `node1` references an object with a content `c.getAReadContent()` whose * value ends up in `node2`. */ +overlay[global] predicate readStep(Node node1, ContentSet c, Node node2) { exists(DataFlow::PropRead read | node1 = read.getBase() and @@ -1487,6 +1533,7 @@ private int firstSpreadArgumentIndex(InvokeExpr expr) { * `node2` references an object with a content `c.getAStoreContent()` that * contains the value of `node1`. */ +overlay[global] predicate storeStep(Node node1, ContentSet c, Node node2) { exists(DataFlow::PropWrite write | node1 = write.getRhs() and @@ -1545,6 +1592,7 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { * any value stored inside `f` is cleared at the pre-update node associated with `x` * in `x.f = newValue`. */ +overlay[global] predicate clearsContent(Node n, ContentSet c) { FlowSummaryPrivate::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c) or @@ -1578,6 +1626,7 @@ predicate clearsContent(Node n, ContentSet c) { * Holds if the value that is being tracked is expected to be stored inside content `c` * at node `n`. */ +overlay[global] predicate expectsContent(Node n, ContentSet c) { FlowSummaryPrivate::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c) or @@ -1602,6 +1651,7 @@ abstract class NodeRegion extends Unit { /** * Holds if the node `n` is unreachable when the call context is `call`. */ +overlay[global] predicate isUnreachableInCall(NodeRegion n, DataFlowCall call) { none() // TODO: could be useful, but not currently implemented for JS } @@ -1635,6 +1685,7 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) } /** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */ +overlay[global] predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode()) and exists(kind) or @@ -1646,6 +1697,7 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } +overlay[global] class ArgumentNode extends DataFlow::Node { ArgumentNode() { isArgumentNodeImpl(this, _, _) } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll index 1711faa4adeb..9595ef935ce0 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll @@ -519,22 +519,23 @@ private module CachedSteps { predicate receiverPropWrite(Function f, string prop, DataFlow::Node rhs) { DataFlow::thisNode(f).hasPropertyWrite(prop, rhs) } - - /** - * Holds if there is a step from `pred` to `succ` through a call to an identity function. - */ - cached - predicate identityFunctionStep(DataFlow::Node pred, DataFlow::CallNode succ) { - exists(DataFlow::GlobalVarRefNode global | - global.getName() = "Object" and - succ.(DataFlow::MethodCallNode).calls(global, ["freeze", "seal"]) and - pred = succ.getArgument(0) - ) - } } import CachedSteps +/** + * Holds if there is a step from `pred` to `succ` through a call to an identity function. + */ +overlay[local] +cached +predicate identityFunctionStep(DataFlow::Node pred, DataFlow::CallNode succ) { + exists(DataFlow::GlobalVarRefNode global | + global.getName() = "Object" and + succ.(DataFlow::MethodCallNode).calls(global, ["freeze", "seal"]) and + pred = succ.getArgument(0) + ) +} + /** * A utility class that is equivalent to `boolean` but does not require type joining. */ diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll index a5131e4fd64e..509aa79eda8c 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll @@ -1,6 +1,8 @@ /** * Provides JS specific classes and predicates for defining flow summaries. */ +overlay[local] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowPrivate @@ -140,6 +142,7 @@ string encodeArgumentPosition(ArgumentPosition pos) { ReturnKind getStandardReturnValueKind() { result = MkNormalReturnKind() and Stage::ref() } private module FlowSummaryStepInput implements Private::StepsInputSig { + overlay[global] DataFlowCall getACall(SummarizedCallable sc) { exists(LibraryCallable callable | callable = sc | result.asOrdinaryCall() = diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableCapture.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableCapture.qll index 8edacdc2f0f9..62892d7e5dbd 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableCapture.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableCapture.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import javascript as js private import semmle.javascript.dataflow.internal.DataFlowNode private import semmle.javascript.dataflow.internal.VariableOrThis diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableOrThis.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableOrThis.qll index a517e0d91fd0..8a3b79a420fe 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableOrThis.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableOrThis.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import javascript private import DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll index 7e610c3c23ce..1dd06c236387 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll @@ -3,6 +3,8 @@ * * JavaScript's old SSA library is still responsible for the ordinary SSA flow. */ +overlay[local] +module; private import javascript as js private import codeql.ssa.Ssa diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll b/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll index 2c460fcc3451..aec8c82247fc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll @@ -1,6 +1,8 @@ /** * Models imports through the NPM `lazy-cache` package. */ +overlay[local] +module; import javascript @@ -58,6 +60,7 @@ module LazyCache { } /** A constant path element appearing in a call to a lazy-cache object. */ + overlay[global] deprecated private class LazyCachePathExpr extends PathExpr, ConstantString { LazyCachePathExpr() { this = any(LazyCacheImport rp).getArgument(0) } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll index 202586227375..c6de3dd7316f 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll @@ -181,9 +181,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashEach extends DataFlow::SummarizedCallable { LodashEach() { this = "_.each-like" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["each", "eachRight", "forEach", "forEachRight", "every", "some"]).getACall() } @@ -195,9 +197,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashMap extends DataFlow::SummarizedCallable { LodashMap() { this = "_.map" } + overlay[global] override DataFlow::CallNode getACall() { result = member("map").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -212,9 +216,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashFlatMap extends DataFlow::SummarizedCallable { LodashFlatMap() { this = "_.flatMap" } + overlay[global] override DataFlow::CallNode getACall() { result = member("flatMap").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -232,9 +238,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashFlatMapDeep extends DataFlow::SummarizedCallable { LodashFlatMapDeep() { this = "_.flatMapDeep" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["flatMapDeep", "flatMapDepth"]).getACall() } @@ -254,9 +262,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashReduce extends DataFlow::SummarizedCallable { LodashReduce() { this = "_.reduce-like" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["reduce", "reduceRight"]).getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -271,9 +281,11 @@ module LodashUnderscore { } } + overlay[local] private class LoashSortBy extends DataFlow::SummarizedCallable { LoashSortBy() { this = "_.sortBy-like" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["sortBy", "orderBy"]).getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -287,9 +299,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashMinMaxBy extends DataFlow::SummarizedCallable { LodashMinMaxBy() { this = "_.minBy / _.maxBy" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["minBy", "maxBy"]).getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -299,9 +313,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashPartition extends DataFlow::SummarizedCallable { LodashPartition() { this = "_.partition" } + overlay[global] override DataFlow::CallNode getACall() { result = member("partition").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -311,9 +327,11 @@ module LodashUnderscore { } } + overlay[local] private class UnderscoreMapObject extends DataFlow::SummarizedCallable { UnderscoreMapObject() { this = "_.mapObject" } + overlay[global] override DataFlow::CallNode getACall() { result = member("mapObject").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -330,9 +348,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashTap extends DataFlow::SummarizedCallable { LodashTap() { this = "_.tap" } + overlay[global] override DataFlow::CallNode getACall() { result = member("tap").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll index c5f8c3d14f1c..89d436bb64c7 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll @@ -8,14 +8,17 @@ import semmle.javascript.security.SensitiveActions private import semmle.javascript.dataflow.internal.PreCallGraphStep module NodeJSLib { + overlay[local] private GlobalVariable processVariable() { variables(result, "process", any(GlobalScope sc)) } + overlay[local] pragma[nomagic] private GlobalVarAccess processExprInTopLevel(TopLevel tl) { result = processVariable().getAnAccess() and tl = result.getTopLevel() } + overlay[local] pragma[nomagic] private GlobalVarAccess processExprInNodeModule() { result = processExprInTopLevel(any(NodeModule m)) @@ -25,6 +28,7 @@ module NodeJSLib { * An access to the global `process` variable in a Node.js module, interpreted as * an import of the `process` module. */ + overlay[local] private class ImplicitProcessImport extends DataFlow::ModuleImportNode::Range { ImplicitProcessImport() { this = DataFlow::exprNode(processExprInNodeModule()) } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll index a7286c7a1999..f1f91785329c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll @@ -1,6 +1,8 @@ /** * Provides predicates for working with templating libraries. */ +overlay[local] +module; import javascript @@ -45,6 +47,7 @@ module Templating { Locatable getParent() { template_placeholder_tag_info(this, result, _) } /** Gets a data flow node representing the value plugged into this placeholder. */ + overlay[global] DataFlow::TemplatePlaceholderTagNode asDataFlowNode() { result.getTag() = this } /** Gets the top-level containing the template expression to be inserted at this placeholder. */ @@ -54,6 +57,7 @@ module Templating { * Holds if this performs raw interpolation, that is, inserts its result * in the output without escaping it. */ + overlay[global] predicate isRawInterpolation() { this.getRawText() .regexpMatch(getLikelyTemplateSyntax(this.getFile()).getRawInterpolationRegexp()) @@ -62,6 +66,7 @@ module Templating { /** * Holds if this performs HTML escaping on the result before inserting it in the template. */ + overlay[global] predicate isEscapingInterpolation() { this.getRawText() .regexpMatch(getLikelyTemplateSyntax(this.getFile()).getEscapingInterpolationRegexp()) @@ -93,6 +98,7 @@ module Templating { * Holds if this placeholder occurs in the definition of another template, which means the output * is susceptible to code injection. */ + overlay[global] predicate isInNestedTemplateContext(string templateType) { templateType = "AngularJS" and AngularJS::isInterpretedByAngularJS(this.getParent()) and @@ -135,6 +141,7 @@ module Templating { * * For example, the call generated from `items | async` would be found by `getAPipeCall("async")`. */ + overlay[global] DataFlow::CallNode getAPipeCall(string name) { result.getCalleeNode().asExpr().(PipeRefExpr).getName() = name } @@ -153,16 +160,19 @@ module Templating { Expr getExpression() { result = this.getChildStmt(0).(ExprStmt).getExpr() } /** Gets the data flow node representing the initialization of the given variable in this scope. */ + overlay[global] DataFlow::Node getVariableInit(string name) { result = DataFlow::ssaDefinitionNode(Ssa::implicitInit(this.getScope().getVariable(name))) } /** Gets a data flow node corresponding to a use of the given template variable within this top-level. */ + overlay[global] DataFlow::SourceNode getAVariableUse(string name) { result = this.getScope().getVariable(name).getAnAccess().flow() } /** Gets a data flow node corresponding to a use of the given template variable within this top-level. */ + overlay[global] DataFlow::SourceNode getAnAccessPathUse(string accessPath) { result = this.getAVariableUse(accessPath) or @@ -177,6 +187,7 @@ module Templating { /** * A place where a template is instantiated or rendered. */ + overlay[global] class TemplateInstantiation extends DataFlow::Node instanceof TemplateInstantiation::Range { /** Gets a data flow node that refers to the instantiated template string, if any. */ DataFlow::SourceNode getOutput() { result = super.getOutput() } @@ -206,6 +217,7 @@ module Templating { } /** Companion module to the `TemplateInstantiation` class. */ + overlay[global] module TemplateInstantiation { abstract class Range extends DataFlow::Node { /** Gets a data flow node that refers to the instantiated template, if any. */ @@ -230,6 +242,7 @@ module Templating { } /** Gets an API node that may flow to `succ` through a template instantiation. */ + overlay[global] private API::Node getTemplateInput(DataFlow::SourceNode succ) { exists(TemplateInstantiation inst, API::Node base, string name | base.asSink() = inst.getTemplateParamsNode() and @@ -258,6 +271,7 @@ module Templating { ) } + overlay[global] private class TemplateInputStep extends DataFlow::SharedFlowStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { getTemplateInput(succ).asSink() = pred @@ -268,6 +282,7 @@ module Templating { * A data flow step from the expression in a placeholder tag to the tag itself, * representing the value plugged into the template. */ + overlay[global] private class TemplatePlaceholderStep extends DataFlow::SharedFlowStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(TemplatePlaceholderTag tag | @@ -281,6 +296,7 @@ module Templating { * A taint step from a `TemplatePlaceholderTag` to the enclosing expression in the * surrounding JavaScript program. */ + overlay[global] private class PlaceholderToGeneratedCodeStep extends TaintTracking::SharedTaintStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(TemplatePlaceholderTag tag | @@ -296,6 +312,7 @@ module Templating { final TemplatePlaceholderTag getAPlaceholder() { result.getFile() = this } /** Gets a template file referenced by this one via a template inclusion tag, such as `{% include foo %}` */ + overlay[global] TemplateFile getAnImportedFile() { result = this.getAPlaceholder().(TemplateInclusionTag).getImportedFile() } @@ -314,6 +331,7 @@ module Templating { * - The root folder is considered unknown, and so a heuristic is used to guess the most * likely template file being referenced. */ + overlay[global] abstract class TemplateFileReference extends DataFlow::Node { /** Gets the value that identifies the template. */ string getValue() { @@ -335,6 +353,7 @@ module Templating { } /** Get file argument of a template instantiation, seen as a template file reference. */ + overlay[global] private class DefaultTemplateFileReference extends TemplateFileReference { DefaultTemplateFileReference() { this = any(TemplateInstantiation inst).getTemplateFileNode() } } @@ -352,6 +371,7 @@ module Templating { * - The root folder is considered unknown, and so a heuristic is used to guess the most * likely template file being referenced. */ + overlay[global] abstract class TemplateFileReferenceString extends string { bindingset[this] TemplateFileReferenceString() { this = this } @@ -382,6 +402,7 @@ module Templating { } /** The value of a template reference node, as a template reference string. */ + overlay[global] private class DefaultTemplateReferenceString extends TemplateFileReferenceString { TemplateFileReference r; @@ -397,6 +418,7 @@ module Templating { } /** The `X` in a path of form `../X`, treated as a separate path string with a different context folder. */ + overlay[global] private class UpwardTraversalSuffix extends TemplateFileReferenceString { TemplateFileReferenceString original; @@ -412,6 +434,7 @@ module Templating { * Gets a "fingerprint" for the given template file, which is used to references * that might refer to it (for pruning purposes only). */ + overlay[global] pragma[nomagic] private string getTemplateFileFingerprint(TemplateFile file) { result = file.getStem() @@ -424,6 +447,7 @@ module Templating { * Gets a "fingerprint" for the given string, which must match one of the fingerprints of * the referenced file (for pruning purposes only). */ + overlay[global] pragma[nomagic] private string getTemplateRefFingerprint(TemplateFileReferenceString ref) { result = ref.getStem() and not result = ["index", ""] @@ -442,6 +466,7 @@ module Templating { * * This is only used to speed up `getAMatchingTarget` by pruning out pairs that can't match. */ + overlay[global] pragma[nomagic] private TemplateFile getAPotentialTarget(TemplateFileReferenceString ref) { getTemplateFileFingerprint(result) = getTemplateRefFingerprint(ref) @@ -467,6 +492,7 @@ module Templating { * Additionally, a file whose stem is `index` matches if `ref` would match the parent folder by * the above rules. For example: `bar` matches `src/bar/index.html`. */ + overlay[global] pragma[nomagic] private TemplateFile getAMatchingTarget(TemplateFileReferenceString ref) { result = getAPotentialTarget(ref) and @@ -491,6 +517,7 @@ module Templating { * The string `list` in `A/components/foo.js` will resolve to `A/views/list.html`, * and vice versa in `B/components/foo.js`. */ + overlay[global] pragma[nomagic] private int getRankOfMatchingTarget( TemplateFile file, Folder baseFolder, TemplateFileReferenceString ref @@ -508,6 +535,7 @@ module Templating { /** * Gets the template file referred to by `ref` when resolved from `baseFolder`. */ + overlay[global] private TemplateFile getBestMatchingTarget(Folder baseFolder, TemplateFileReferenceString ref) { result = max(getAMatchingTarget(ref) as f order by getRankOfMatchingTarget(f, baseFolder, ref)) } @@ -599,6 +627,7 @@ module Templating { override string getAPackageName() { result = "dot" } } + overlay[global] private TemplateSyntax getOwnTemplateSyntaxInFolder(Folder f) { exists(PackageDependencies deps | deps.getADependency(result.getAPackageName(), _) and @@ -606,6 +635,7 @@ module Templating { ) } + overlay[global] private TemplateSyntax getTemplateSyntaxInFolder(Folder f) { result = getOwnTemplateSyntaxInFolder(f) or @@ -613,6 +643,7 @@ module Templating { result = getTemplateSyntaxInFolder(f.getParentContainer()) } + overlay[global] private TemplateSyntax getTemplateSyntaxFromInstantiation(TemplateFile file) { result = any(TemplateInstantiation inst | inst.getTemplateFile() = file).getTemplateSyntax() } @@ -620,6 +651,7 @@ module Templating { /** * Gets a template syntax likely to be used in the given file. */ + overlay[global] TemplateSyntax getLikelyTemplateSyntax(TemplateFile file) { result = getTemplateSyntaxFromInstantiation(file) or @@ -632,6 +664,7 @@ module Templating { } /** A step through the `safe` pipe, which bypasses HTML escaping. */ + overlay[global] private class SafePipeStep extends TaintTracking::SharedTaintStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(DataFlow::CallNode call | @@ -645,6 +678,7 @@ module Templating { /** * An EJS-style `include` call within a template tag, such as `<%- include(file, { params }) %>`. */ + overlay[global] private class EjsIncludeCallInTemplate extends TemplateInstantiation::Range, DataFlow::CallNode { EjsIncludeCallInTemplate() { exists(TemplatePlaceholderTag tag | @@ -669,6 +703,7 @@ module Templating { * * These API nodes are used in the `getTemplateInput` predicate. */ + overlay[global] private class IncludeFunctionAsEntryPoint extends API::EntryPoint { IncludeFunctionAsEntryPoint() { this = "IncludeFunctionAsEntryPoint" } @@ -703,6 +738,7 @@ module Templating { string getPath() { result = rawPath.trim().replaceAll("\\", "/").regexpReplaceAll("^\\./", "") } /** Gets the file referenced by this inclusion tag. */ + overlay[global] TemplateFile getImportedFile() { result = this.getPath() @@ -712,6 +748,7 @@ module Templating { } /** The imported string from a template inclusion tag. */ + overlay[global] private class TemplateInclusionPathString extends TemplateFileReferenceString { TemplateInclusionTag tag; @@ -723,6 +760,7 @@ module Templating { /** * A call to a member of the `consolidate` library, seen as a template instantiation. */ + overlay[global] private class ConsolidateCall extends TemplateInstantiation::Range, API::CallNode { string engine; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll index 90dcc886ed43..9097497b4f07 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll @@ -422,9 +422,11 @@ private module ClosureLibraryUri { } } +overlay[local] private class QueryStringStringification extends DataFlow::SummarizedCallable { QueryStringStringification() { this = "query-string stringification" } + overlay[global] override DataFlow::InvokeNode getACall() { result = API::moduleImport(["querystring", "query-string", "querystringify", "qs"]) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll index 82deb735c629..9e7f94c139b7 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll @@ -48,6 +48,7 @@ private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Rang } } +overlay[local] private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable { string type; string path; @@ -57,6 +58,7 @@ private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable { this = type + ";" + path } + overlay[global] override DataFlow::InvokeNode getACall() { ModelOutput::resolvedSummaryBase(type, path, result) } override predicate propagatesFlow( diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll index c04a85487acf..80ec45a3cf17 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll @@ -62,6 +62,8 @@ * should be prefixed with a tilde character (`~`). For example, `~Bar` can be used to indicate that * the type is not intended to match a static type. */ +overlay[local?] +module; private import codeql.util.Unit private import ApiGraphModelsSpecific as Specific diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll index 4969da43be34..3f38c498f324 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll @@ -1,6 +1,8 @@ /** * Defines extensible predicates for contributing library models from data extensions. */ +overlay[local] +module; /** * Holds if the value at `(type, path)` should be seen as a flow diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll index f0d751ad31b6..a6ab3d691b5d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -41,6 +41,7 @@ class Location = JS::Location; * The model generator must explicitly generate the step between `(package)` and `(package).foo`, for example. */ bindingset[rawType] +overlay[caller] predicate parseTypeString(string rawType, string package, string qualifiedName) { exists(string regexp | regexp = "('[^']+'|[^.]+)(.*)" and @@ -55,6 +56,7 @@ predicate parseTypeString(string rawType, string package, string qualifiedName) /** * Holds if models describing `package` may be relevant for the analysis of this database. */ +overlay[local] predicate isPackageUsed(string package) { package = "global" or @@ -68,6 +70,7 @@ predicate isPackageUsed(string package) { } bindingset[type] +overlay[local] predicate isTypeUsed(string type) { exists(string package | parseTypeString(type, package, _) and @@ -79,8 +82,10 @@ predicate isTypeUsed(string type) { * Holds if `type` can be obtained from an instance of `otherType` due to * language semantics modeled by `getExtraNodeFromType`. */ +overlay[local] predicate hasImplicitTypeModel(string type, string otherType) { none() } +overlay[local] pragma[nomagic] private predicate parseRelevantTypeString(string rawType, string package, string qualifiedName) { isRelevantFullPath(rawType, _) and diff --git a/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll b/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll index d8e4a18dfc17..cf34b6bdb162 100644 --- a/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll +++ b/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll @@ -2,6 +2,8 @@ * Provides classes for working with basic blocks, and predicates for computing * liveness information for local variables. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.StmtContainers diff --git a/javascript/ql/lib/semmle/javascript/internal/CachedStages.qll b/javascript/ql/lib/semmle/javascript/internal/CachedStages.qll index 98a35692822e..ae9fe0bce271 100644 --- a/javascript/ql/lib/semmle/javascript/internal/CachedStages.qll +++ b/javascript/ql/lib/semmle/javascript/internal/CachedStages.qll @@ -40,6 +40,7 @@ module Stages { /** * The `ast` stage. */ + overlay[local] cached module Ast { /** @@ -84,6 +85,7 @@ module Stages { /** * The `basicblocks` stage. */ + overlay[local] cached module BasicBlocks { /** @@ -110,6 +112,7 @@ module Stages { /** * The part of data flow computed before flow summary nodes. */ + overlay[local] cached module EarlyDataFlowStage { /** @@ -134,6 +137,7 @@ module Stages { /** * The `dataflow` stage. */ + overlay[local] cached module DataFlowStage { /** @@ -167,8 +171,8 @@ module Stages { or exists(any(DataFlow::PropRef ref).getBase()) or - exists(any(DataFlow::ClassNode cls)) - or + // exists(any(DataFlow::ClassNode cls)) // Depends on AnalyzedNode + // or exists(any(DataFlow::CallNode node).getArgument(_)) or exists(any(DataFlow::CallNode node).getAnArgument()) @@ -202,8 +206,6 @@ module Stages { or exists(any(Import i).getImportedModule()) or - exists(DataFlow::moduleImport(_)) - or exists(any(ReExportDeclaration d).getReExportedModule()) or exists(any(Module m).getABulkExportedNode()) diff --git a/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll b/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll index a1df0504ce81..ab867be307b4 100644 --- a/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll +++ b/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll @@ -4,6 +4,8 @@ * Provides predicates and classes for relating nodes to their * enclosing `StmtContainer`. */ +overlay[local] +module; private import javascript private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll index 45ad9cf7a9c9..4e1c9ee6884e 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll @@ -20,6 +20,8 @@ * * (Promise is absent in the table above as there currently are no name clashes with Promise methods) */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll index 6754d3db3071..1196ffdbac9c 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll @@ -3,6 +3,8 @@ * * Note that some of Array methods are modeled in `AmbiguousCoreMethods.qll`, and `toString` is special-cased elsewhere. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AsyncAwait.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AsyncAwait.qll index 246ac0f19d08..6a33c9a5c4fb 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AsyncAwait.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AsyncAwait.qll @@ -1,6 +1,8 @@ /** * Contains flow steps to model flow through `async` functions and the `await` operator. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll index 2866c8926087..80e43fdfcd8c 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.FlowSummary private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/DynamicImportStep.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/DynamicImportStep.qll index 2976b4673150..2661802b97e5 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/DynamicImportStep.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/DynamicImportStep.qll @@ -1,6 +1,8 @@ /** * Contains flow steps to model flow from a module into a dynamic `import()` expression. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll index 252baab207bb..3dff015d9f37 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll @@ -1,6 +1,8 @@ /** * Contains a summary for propagating exceptions out of callbacks */ +overlay[local?] +module; private import javascript private import FlowSummaryUtil diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll index 33f891935f42..290567efbd9d 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.FlowSummary private import semmle.javascript.dataflow.internal.Contents::Private diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll index ecc84170026f..68298c3fb554 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll @@ -1,6 +1,8 @@ /** * Contains flow steps to model flow through `for..of` loops. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Generators.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Generators.qll index 75815d00341d..4f0868db5196 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Generators.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Generators.qll @@ -1,6 +1,8 @@ /** * Contains flow steps to model flow through generator functions. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll index 6b1a182a49bd..7f9c13c63dfd 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through iterators. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll index ecd2dcdfc79b..4b8ecdeb4f28 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll @@ -1,6 +1,8 @@ /** * Contains implicit read steps at the input to any function that converts a deep object to a string, such as `JSON.stringify`. */ +overlay[local?] +module; private import javascript private import FlowSummaryUtil diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll index d9649d407c61..645e36941dc3 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through `Map` objects. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll index 74048f0e397e..10292958df2f 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through `Promise` objects. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll index 6b4f089b38ec..e4d0951764f1 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through `Set` objects. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll index bf9442219a75..b5ecc8ef603c 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through string methods. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll index 19a28036db49..0ac2307c81a5 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.FlowSummary private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll index 0a47b6fcf9f5..3d8d88d8ae47 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll @@ -3,6 +3,8 @@ * * For now, the `URLSearchParams` object is modeled as a `Map` object. */ +overlay[local?] +module; private import javascript From 4950fa0ca5eb77d12261f6fbdabdc01a7d5b14ea Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 3 Oct 2025 10:43:49 +0200 Subject: [PATCH 02/59] JS: Fix getRawEnclosingStmt call --- javascript/ql/lib/semmle/javascript/Expr.qll | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/Expr.qll b/javascript/ql/lib/semmle/javascript/Expr.qll index 177ef6991ce3..ede0e7094abd 100644 --- a/javascript/ql/lib/semmle/javascript/Expr.qll +++ b/javascript/ql/lib/semmle/javascript/Expr.qll @@ -249,12 +249,6 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { ) } - pragma[inline] - private Stmt getRawEnclosingStmt(Expr e) { - // For performance reasons, we need the enclosing statement without overrides - enclosing_stmt(e, result) - } - /** * Gets the data-flow node where exceptions thrown by this expression will * propagate if this expression causes an exception to be thrown. @@ -262,9 +256,9 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { overlay[caller] pragma[inline] DataFlow::Node getExceptionTarget() { - result = getCatchParameterFromStmt(this.getRawEnclosingStmt(this)) + result = getCatchParameterFromStmt(getRawEnclosingStmt(this)) or - not exists(getCatchParameterFromStmt(this.getRawEnclosingStmt(this))) and + not exists(getCatchParameterFromStmt(getRawEnclosingStmt(this))) and result = any(DataFlow::FunctionNode f | f.getFunction() = this.getContainer()).getExceptionalReturn() } @@ -277,6 +271,13 @@ private DataFlow::Node getCatchParameterFromStmt(Stmt stmt) { DataFlow::parameterNode(stmt.getEnclosingTryCatchStmt().getACatchClause().getAParameter()) } +overlay[caller] +pragma[inline] +private Stmt getRawEnclosingStmt(Expr e) { + // For performance reasons, we need the enclosing statement without overrides + enclosing_stmt(e, result) +} + /** * An identifier. * From afa8cd90a2b25d934db933880dbd26b7cf680db7 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 13:27:46 +0200 Subject: [PATCH 03/59] JS: Add overlay[local?] to new summaries after rebasing --- javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll | 2 ++ .../ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll | 1 + 2 files changed, 3 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll b/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll index db2487ce46a0..c95b7a8dc6a1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll @@ -172,6 +172,7 @@ module AsyncPackage { DataFlow::FunctionNode getFinalCallback() { result = this.getCallback(finalCallbackIndex) } } + overlay[local?] private class IterationCallFlowSummary extends DataFlow::SummarizedCallable { private int callbackArgIndex; @@ -219,6 +220,7 @@ module AsyncPackage { * * For example: `data -> result` in `async.sortBy(data, orderingFn, (err, result) => {})`. */ + overlay[local?] private class IterationPreserveTaintStepFlowSummary extends DataFlow::SummarizedCallable { IterationPreserveTaintStepFlowSummary() { this = "async.sortBy" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll index c6de3dd7316f..3c6c4511f5be 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll @@ -362,6 +362,7 @@ module LodashUnderscore { } } + overlay[local?] private class LodashGroupBy extends DataFlow::SummarizedCallable { LodashGroupBy() { this = "_.groupBy" } From eded45a6fc8e708f66e70a5bc4c444c7edd64a26 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 09:46:49 +0200 Subject: [PATCH 04/59] JS: Make more general-purpose data flow things local --- javascript/ql/lib/semmle/javascript/Extend.qll | 4 ++++ javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll | 4 +++- .../semmle/javascript/frameworks/AngularJS/AngularJSCore.qll | 1 + .../ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll | 4 ++++ .../lib/semmle/javascript/frameworks/PropertyProjection.qll | 3 +++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/Extend.qll b/javascript/ql/lib/semmle/javascript/Extend.qll index d0eeade58928..e59c11d225ee 100644 --- a/javascript/ql/lib/semmle/javascript/Extend.qll +++ b/javascript/ql/lib/semmle/javascript/Extend.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about `extend`-like functions. */ +overlay[local] +module; import javascript @@ -169,6 +171,7 @@ private class FunctionalExtendCallShallow extends ExtendCall { * * Since all object properties are preserved, we model this as a value-preserving step. */ +overlay[global] private class ExtendCallStep extends PreCallGraphStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(ExtendCall extend | @@ -184,6 +187,7 @@ private import semmle.javascript.dataflow.internal.PreCallGraphStep /** * A step through a cloning library, such as `clone` or `fclone`. */ +overlay[global] private class CloneStep extends PreCallGraphStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(DataFlow::CallNode call | diff --git a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll index 4a461961f8af..32fe6f709ca0 100644 --- a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll @@ -1,6 +1,8 @@ /** * Provides predicates for associating qualified names with data flow nodes. */ +overlay[local] +module; import javascript private import semmle.javascript.dataflow.InferredTypes @@ -657,7 +659,7 @@ module AccessPath { */ cached predicate hasDominatingWrite(DataFlow::PropRead read) { - Stages::TypeTracking::ref() and + Stages::DataFlowStage::ref() and // within the same basic block. exists(ReachableBasicBlock bb, Root root, string path, int ranking | read.asExpr() = rankedAccessPath(bb, root, path, ranking, AccessPathRead()) and diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index 41d14c1e3be4..beb601dcfb9e 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -15,6 +15,7 @@ private import AngularJS /** * Holds if `nd` is a reference to the `angular` variable. */ +overlay[local] DataFlow::SourceNode angular() { // either as a global result = DataFlow::globalVarRef("angular") diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll index 3c6c4511f5be..fe07e4f19678 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll @@ -9,6 +9,7 @@ module LodashUnderscore { /** * A data flow node that accesses a given member of `lodash` or `underscore`. */ + overlay[local] abstract class Member extends DataFlow::SourceNode { /** Gets the name of the accessed member. */ abstract string getName(); @@ -17,6 +18,7 @@ module LodashUnderscore { /** * An import of `lodash` or `underscore` accessing a given member of that package. */ + overlay[local] private class DefaultMember extends Member { string name; @@ -39,12 +41,14 @@ module LodashUnderscore { * In addition to normal imports, this supports per-method imports such as `require("lodash.map")` and `require("lodash/map")`. * In addition, the global variable `_` is assumed to refer to `lodash` or `underscore`. */ + overlay[local] DataFlow::SourceNode member(string name) { result.(Member).getName() = name } /** * Holds if `name` is the name of a member exported from the `lodash` package * which has a corresponding `lodash.xxx` NPM package. */ + overlay[local] private predicate isLodashMember(string name) { // Can be generated using Object.keys(require('lodash')) name = diff --git a/javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll b/javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll index 11fb0f5ceba5..c0188361e72a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll @@ -4,6 +4,8 @@ * Subclass `PropertyProjection` to refine the behavior of the analysis on existing property projections. * Subclass `CustomPropertyProjection` to introduce new kinds of property projections. */ +overlay[local] +module; import javascript @@ -137,6 +139,7 @@ private class VarArgsPropertyProjection extends PropertyProjection::Range { /** * A taint step for a property projection. */ +overlay[global] private class PropertyProjectionTaintStep extends TaintTracking::SharedTaintStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { // reading from a tainted object yields a tainted result From 1da2fc9009cf986c1e77caef854161430bd08f32 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 10 Oct 2025 15:10:17 +0000 Subject: [PATCH 05/59] JS: Overlay annotations for some failing tests Locally these seem to get rid of the compilation warnings, but of course CI is the true arbiter here. --- javascript/ql/lib/utils/test/InlineSummaries.qll | 1 + javascript/ql/test/library-tests/AMD/tests.ql | 1 + .../CustomAbstractValueDefinitions.ql | 1 + .../CustomAbstractValueDefinitionsFlow.ql | 1 + .../ql/test/library-tests/FlowCustomisation/customValues.ql | 2 ++ .../ql/test/library-tests/ModuleImportNodes/CustomImport.ql | 1 + .../test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql | 1 + javascript/ql/test/library-tests/frameworks/data/test.ql | 1 + javascript/ql/test/library-tests/frameworks/data/warnings.ql | 1 + 9 files changed, 10 insertions(+) diff --git a/javascript/ql/lib/utils/test/InlineSummaries.qll b/javascript/ql/lib/utils/test/InlineSummaries.qll index 559f13609778..0366736eaf66 100644 --- a/javascript/ql/lib/utils/test/InlineSummaries.qll +++ b/javascript/ql/lib/utils/test/InlineSummaries.qll @@ -1,6 +1,7 @@ import javascript import semmle.javascript.dataflow.FlowSummary +overlay[local] class MkSummary extends SummarizedCallable { private CallExpr mkSummary; diff --git a/javascript/ql/test/library-tests/AMD/tests.ql b/javascript/ql/test/library-tests/AMD/tests.ql index e71ae089f2d4..150c5e9a294d 100644 --- a/javascript/ql/test/library-tests/AMD/tests.ql +++ b/javascript/ql/test/library-tests/AMD/tests.ql @@ -1,5 +1,6 @@ import javascript +overlay[local] class TestAmdModuleRange extends AmdModuleDefinition::Range { TestAmdModuleRange() { this.getCallee().(PropAccess).getQualifiedName() = "test.amd.range" } } diff --git a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql index a2d69f55ce82..c0571921fba8 100644 --- a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql +++ b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql @@ -4,6 +4,7 @@ import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps import semmle.javascript.dataflow.internal.AbstractPropertiesImpl as AbstractPropertiesImpl import semmle.javascript.dataflow.CustomAbstractValueDefinitions +overlay[local] class MyCustomAbstractValueDefinition extends CustomAbstractValueDefinition { DataFlow::ValueNode node; diff --git a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql index 0308ad6bf455..0f34b14b48c5 100644 --- a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql +++ b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql @@ -2,6 +2,7 @@ import javascript import semmle.javascript.dataflow.InferredTypes import semmle.javascript.dataflow.CustomAbstractValueDefinitions +overlay[local] class MyCustomAbstractValueDefinition extends CustomAbstractValueDefinition, AST::ValueNode { MyCustomAbstractValueDefinition() { this.flow() instanceof DataFlow::ObjectLiteralNode and diff --git a/javascript/ql/test/library-tests/FlowCustomisation/customValues.ql b/javascript/ql/test/library-tests/FlowCustomisation/customValues.ql index 0b3f87f1b8d2..75c4af21ed74 100644 --- a/javascript/ql/test/library-tests/FlowCustomisation/customValues.ql +++ b/javascript/ql/test/library-tests/FlowCustomisation/customValues.ql @@ -4,6 +4,7 @@ private import semmle.javascript.dataflow.InferredTypes /** * A custom abstract value representing the DOM object `document`. */ +overlay[local] class Document extends CustomAbstractValueTag { Document() { this = "document" } @@ -25,6 +26,7 @@ class Document extends CustomAbstractValueTag { * Note that `getType()` isn't quite right, since `typeof document.all === 'undefined'`, * but that's fine for the purposes of this test. */ +overlay[local] class DocumentAll extends CustomAbstractValueTag { DocumentAll() { this = "document.all" } diff --git a/javascript/ql/test/library-tests/ModuleImportNodes/CustomImport.ql b/javascript/ql/test/library-tests/ModuleImportNodes/CustomImport.ql index abc8c4e17555..c118e36e6067 100644 --- a/javascript/ql/test/library-tests/ModuleImportNodes/CustomImport.ql +++ b/javascript/ql/test/library-tests/ModuleImportNodes/CustomImport.ql @@ -1,5 +1,6 @@ import javascript +overlay[local] class CustomImport extends DataFlow::ModuleImportNode::Range, DataFlow::CallNode { CustomImport() { this.getCalleeName() = "customImport" } diff --git a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql index 9a5350948fe2..a9d27450aee4 100644 --- a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql +++ b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql @@ -7,6 +7,7 @@ import javascript +overlay[local] class BadSourceNode extends DataFlow::SourceNode { BadSourceNode() { this.(DataFlow::PropRead).getPropertyName() = "foo" } diff --git a/javascript/ql/test/library-tests/frameworks/data/test.ql b/javascript/ql/test/library-tests/frameworks/data/test.ql index 6a1d571351b4..6ba504e921fa 100644 --- a/javascript/ql/test/library-tests/frameworks/data/test.ql +++ b/javascript/ql/test/library-tests/frameworks/data/test.ql @@ -2,6 +2,7 @@ import javascript deprecated import utils.test.ConsistencyChecking import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels +overlay[local] class TypeModelFromCodeQL extends ModelInput::TypeModel { override predicate isTypeUsed(string type) { type = "danger-constant" } diff --git a/javascript/ql/test/library-tests/frameworks/data/warnings.ql b/javascript/ql/test/library-tests/frameworks/data/warnings.ql index 1ede8e08bcc2..2c3c044ef694 100644 --- a/javascript/ql/test/library-tests/frameworks/data/warnings.ql +++ b/javascript/ql/test/library-tests/frameworks/data/warnings.ql @@ -1,6 +1,7 @@ import javascript import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels +overlay[local] class IsTesting extends ApiGraphModels::TestAllModels { IsTesting() { this = this } } From cfda393d3beb8391cfed6b4a92e7a7a0c64a853c Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 15 Oct 2025 10:46:42 +0200 Subject: [PATCH 06/59] JS: Add some overlay[caller] and a pragma[nomagic] annotations --- .../ql/lib/semmle/javascript/GlobalAccessPaths.qll | 9 +++++++++ .../javascript/dataflow/internal/DataFlowPrivate.qll | 2 ++ .../semmle/javascript/internal/BasicBlockInternal.qll | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll index 32fe6f709ca0..804542b0dc56 100644 --- a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll @@ -356,6 +356,7 @@ module AccessPath { * Gets a variable that is relevant for the computations in the `GetLaterAccess` module. * This predicate restricts as much as it can, but without depending on `getAVariableRef`. */ + overlay[caller] pragma[inline] private SsaVariable getARelevantVariableSimple() { // The variable might be used where `getLaterBaseAccess()` is called. @@ -407,6 +408,7 @@ module AccessPath { * } * ``` */ + overlay[caller] pragma[inline] DataFlow::Node getAReferenceTo(Root root, string path) { path = fromReference(result, root) and @@ -430,6 +432,7 @@ module AccessPath { * })(NS = NS || {}); * ``` */ + overlay[caller] pragma[inline] DataFlow::Node getAReferenceTo(string path) { path = fromReference(result, DataFlow::globalAccessPathRootPseudoNode()) @@ -451,6 +454,7 @@ module AccessPath { * } * ``` */ + overlay[caller] pragma[inline] DataFlow::Node getAnAssignmentTo(Root root, string path) { path = fromRhs(result, root) and @@ -472,6 +476,7 @@ module AccessPath { * })(foo = foo || {}); * ``` */ + overlay[caller] pragma[inline] DataFlow::Node getAnAssignmentTo(string path) { path = fromRhs(result, DataFlow::globalAccessPathRootPseudoNode()) @@ -482,6 +487,7 @@ module AccessPath { * * See `getAReferenceTo` and `getAnAssignmentTo` for more details. */ + overlay[caller] pragma[inline] DataFlow::Node getAReferenceOrAssignmentTo(string path) { result = getAReferenceTo(path) @@ -494,6 +500,7 @@ module AccessPath { * * See `getAReferenceTo` and `getAnAssignmentTo` for more details. */ + overlay[caller] pragma[inline] DataFlow::Node getAReferenceOrAssignmentTo(Root root, string path) { result = getAReferenceTo(root, path) @@ -504,6 +511,7 @@ module AccessPath { /** * Holds if there is a step from `pred` to `succ` through an assignment to an access path. */ + overlay[caller] pragma[inline] predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(string name, Root root | @@ -521,6 +529,7 @@ module AccessPath { /** * Gets a `SourceNode` that refers to the same value or access path as the given node. */ + overlay[caller] pragma[inline] DataFlow::SourceNode getAnAliasedSourceNode(DataFlow::Node node) { exists(DataFlow::SourceNode root, string accessPath | diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll index 68cf0aa4287b..88217800f488 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll @@ -1493,6 +1493,7 @@ private predicate stringifiedNode(Node node) { } /** Gets the post-update node for which `node` is the corresponding pre-update node. */ +pragma[nomagic] private Node getPostUpdateForStore(Node base) { exists(Expr expr | base = TValueNode(expr) and @@ -1515,6 +1516,7 @@ private Node getPostUpdateForStore(Node base) { } /** Gets node to target with a store to the given `base` object.. */ +overlay[caller] pragma[inline] private Node getStoreTarget(DataFlow::Node base) { result = getPostUpdateForStore(base) diff --git a/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll b/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll index cf34b6bdb162..d422c960a8fc 100644 --- a/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll +++ b/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll @@ -320,6 +320,7 @@ module Public { /** * Holds if this basic block strictly dominates `bb`. */ + overlay[caller] pragma[inline] predicate strictlyDominates(ReachableBasicBlock bb) { this = immediateDominator+(bb) } @@ -328,12 +329,14 @@ module Public { * * This predicate is reflexive: each reachable basic block dominates itself. */ + overlay[caller] pragma[inline] predicate dominates(ReachableBasicBlock bb) { this = immediateDominator*(bb) } /** * Holds if this basic block strictly post-dominates `bb`. */ + overlay[caller] pragma[inline] predicate strictlyPostDominates(ReachableBasicBlock bb) { this = immediatePostDominator+(bb) } @@ -342,6 +345,7 @@ module Public { * * This predicate is reflexive: each reachable basic block post-dominates itself. */ + overlay[caller] pragma[inline] predicate postDominates(ReachableBasicBlock bb) { this = immediatePostDominator*(bb) } } From b86d88f46464f6c03d330c166be65ed3b13f7dc0 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 15 Oct 2025 11:05:22 +0200 Subject: [PATCH 07/59] JS: Add more overlay[caller?] annotations --- javascript/ql/lib/semmle/javascript/AST.qll | 1 + javascript/ql/lib/semmle/javascript/Locations.qll | 2 ++ javascript/ql/lib/semmle/javascript/Promises.qll | 2 ++ javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll | 1 + .../ql/lib/semmle/javascript/dataflow/internal/Contents.qll | 1 + .../lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll | 1 + .../ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll | 1 + .../lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll | 1 + .../frameworks/data/internal/ApiGraphModelsSpecific.qll | 2 ++ javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll | 1 + 10 files changed, 13 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/AST.qll b/javascript/ql/lib/semmle/javascript/AST.qll index 6a0d35abea50..0467847a9a04 100644 --- a/javascript/ql/lib/semmle/javascript/AST.qll +++ b/javascript/ql/lib/semmle/javascript/AST.qll @@ -174,6 +174,7 @@ class AstNode extends @ast_node, NodeInStmtContainer { * The TypeScript compiler emits no code for ambient declarations, but they * can affect name resolution and type checking at compile-time. */ + overlay[caller?] pragma[inline] predicate isAmbient() { this.isAmbientInternal() diff --git a/javascript/ql/lib/semmle/javascript/Locations.qll b/javascript/ql/lib/semmle/javascript/Locations.qll index 87b41c2cb43f..1c48a3adbd3f 100644 --- a/javascript/ql/lib/semmle/javascript/Locations.qll +++ b/javascript/ql/lib/semmle/javascript/Locations.qll @@ -32,6 +32,7 @@ final class Location extends @location_default { int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 } /** Holds if this location starts before location `that`. */ + overlay[caller] pragma[inline] predicate startsBefore(Location that) { exists(string f, int sl1, int sc1, int sl2, int sc2 | @@ -45,6 +46,7 @@ final class Location extends @location_default { } /** Holds if this location ends after location `that`. */ + overlay[caller] pragma[inline] predicate endsAfter(Location that) { exists(string f, int el1, int ec1, int el2, int ec2 | diff --git a/javascript/ql/lib/semmle/javascript/Promises.qll b/javascript/ql/lib/semmle/javascript/Promises.qll index dfdcdfd632cb..f373ca87d39a 100644 --- a/javascript/ql/lib/semmle/javascript/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/Promises.qll @@ -238,6 +238,7 @@ module PromiseTypeTracking { * * These type-tracking steps are already included in the default type-tracking steps (through `PreCallGraphStep`). */ + overlay[caller?] pragma[inline] DataFlow::Node promiseStep(DataFlow::Node pred, StepSummary summary) { exists(string field | field = Promises::valueProp() | @@ -256,6 +257,7 @@ module PromiseTypeTracking { * Gets the result from a single step through a promise, from `pred` with tracker `t2` to `result` with tracker `t`. * This can be loading a resolved value from a promise, storing a value in a promise, or copying a resolved value from one promise to another. */ + overlay[caller?] pragma[inline] DataFlow::SourceNode promiseStep( DataFlow::SourceNode pred, DataFlow::TypeTracker t, DataFlow::TypeTracker t2 diff --git a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll index a61b67e643fe..9d4bda428b52 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll @@ -1436,6 +1436,7 @@ module DataFlow { /** * Gets the data flow node corresponding to `e`. */ + overlay[caller?] pragma[inline] ExprNode exprNode(Expr e) { result = valueNode(e) } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll index be9bc2c81a3d..d29a450274e9 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll @@ -197,6 +197,7 @@ module Public { */ class ContentSet extends TContentSet { /** Gets a content that may be stored into when storing into this set. */ + overlay[caller?] pragma[inline] Content getAStoreContent() { result = this.asSingleton() diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll index 88217800f488..24549e7f1e6b 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll @@ -762,6 +762,7 @@ class ContentApprox extends TContentApprox { } } +overlay[global] pragma[inline] ContentApprox getContentApprox(Content c) { c instanceof MkPropertyContent and result = TApproxPropertyContent() diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll index 9595ef935ce0..0f5eff532586 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll @@ -48,6 +48,7 @@ private predicate legacyPostUpdateStep(DataFlow::Node pred, DataFlow::Node succ) * Holds if data can flow in one step from `pred` to `succ`, taking * additional steps from the configuration into account. */ +overlay[caller?] pragma[inline] deprecated predicate localFlowStep( DataFlow::Node pred, DataFlow::Node succ, DataFlow::Configuration configuration, diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll index 1dd06c236387..edea8ed6c387 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll @@ -96,6 +96,7 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig { } } + overlay[caller?] pragma[inline] predicate guardDirectlyControlsBlock(Guard guard, js::Cfg::BasicBlock bb, GuardValue branch) { exists(js::ConditionGuardNode g | diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll index a6ab3d691b5d..2074b18600dc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -195,6 +195,7 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token) { } bindingset[node] +overlay[caller?] pragma[inline_late] private API::Node getAGuardedRouteHandlerApprox(API::Node node) { // For now just get any routing node with the same root (i.e. the same web app), as @@ -235,6 +236,7 @@ private predicate blockFuzzyCall(DataFlow::CallNode call) { isCommonBuiltinMethodName(call.getCalleeName()) } +overlay[caller?] pragma[inline] API::Node getAFuzzySuccessor(API::Node node) { result = node.getAMember() and diff --git a/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll b/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll index ab867be307b4..741575c3242c 100644 --- a/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll +++ b/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll @@ -48,6 +48,7 @@ class NodeInStmtContainer extends Locatable, @node_in_stmt_container { /** * Gets the function or toplevel to which this node belongs. */ + overlay[caller] pragma[inline] final StmtContainer getContainer() { result = getStmtContainer(this) } } From fd96b72eb8fe039f234472a9c606816631815394 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 16 Oct 2025 12:01:57 +0200 Subject: [PATCH 08/59] JS: Fix bad join in DuplicateProperty.ql --- .../ql/src/Expressions/DuplicateProperty.ql | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Expressions/DuplicateProperty.ql b/javascript/ql/src/Expressions/DuplicateProperty.ql index febdfe5b8826..b13f1a93ec0d 100644 --- a/javascript/ql/src/Expressions/DuplicateProperty.ql +++ b/javascript/ql/src/Expressions/DuplicateProperty.ql @@ -14,12 +14,26 @@ import Clones +bindingset[init] +pragma[inline_late] +private Property getPropertyFromInitializerStrict(Expr init) { result.getInit() = init } + +pragma[nomagic] +private predicate duplicateProperties( + DuplicatePropertyInitDetector dup, Property prop1, Property prop2 +) { + exists(Expr init2 | + dup.same(init2) and + prop1 = getPropertyFromInitializerStrict(dup) and + prop2 = getPropertyFromInitializerStrict(init2) + ) +} + from ObjectExpr oe, int i, int j, Property p, Property q, DuplicatePropertyInitDetector dpid where + duplicateProperties(dpid, p, q) and p = oe.getProperty(i) and q = oe.getProperty(j) and - dpid = p.getInit() and - dpid.same(q.getInit()) and i < j and // only report the next duplicate not exists(int mid | mid in [i + 1 .. j - 1] | dpid.same(oe.getProperty(mid).getInit())) From 1bcb2eab9611ffed152c4bd0e8f20edd6270b049 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 16 Oct 2025 12:22:18 +0200 Subject: [PATCH 09/59] JS: Add overlay[local] to restore magic in unwrap() predicate In this case we actually want magic to apply, but was prevented by locality. --- javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll b/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll index ed53158d51c9..e8b235eca9b0 100644 --- a/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll +++ b/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll @@ -1,6 +1,8 @@ /** * Provides a predicate for identifying unused index variables in loops. */ +overlay[local] +module; import javascript From 88351d5447cc5631cf4226ab054cf99a326ae31c Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 16 Oct 2025 12:22:45 +0200 Subject: [PATCH 10/59] JS: Avoid bad join in shared predicate induced by 'forex'. Use manual recursion instead. --- javascript/ql/lib/semmle/javascript/Expr.qll | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/Expr.qll b/javascript/ql/lib/semmle/javascript/Expr.qll index ede0e7094abd..b46faf7e2b79 100644 --- a/javascript/ql/lib/semmle/javascript/Expr.qll +++ b/javascript/ql/lib/semmle/javascript/Expr.qll @@ -1648,13 +1648,19 @@ private string getConstantString(Expr e) { result = e.(TemplateElement).getValue() } +pragma[nomagic] +private predicate hasConstantStringValue(Expr e) { + exists(getConstantString(e)) + or + hasAllConstantLeafs(e.getUnderlyingValue()) +} + /** * Holds if `add` is a string-concatenation where all the transitive leafs have a constant string value. */ private predicate hasAllConstantLeafs(AddExpr add) { - forex(Expr leaf | leaf = getAnAddOperand*(add) and not exists(getAnAddOperand(leaf)) | - exists(getConstantString(leaf)) - ) + hasConstantStringValue(add.getLeftOperand()) and + hasConstantStringValue(add.getRightOperand()) } /** From 8dd1a9e7cb4b85a97fd0f6b53094b3d93938e7c7 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 20 Oct 2025 11:57:39 +0200 Subject: [PATCH 11/59] JS: Avoid more bad joins due to locality --- javascript/ql/lib/semmle/javascript/AST.qll | 2 ++ javascript/ql/lib/semmle/javascript/Regexp.qll | 16 +++++++++++++--- .../lib/semmle/javascript/dataflow/DataFlow.qll | 1 + .../semmle/javascript/frameworks/LazyCache.qll | 4 ++-- .../internal/flow_summaries/ForOfLoops.qll | 10 ++++++++-- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/AST.qll b/javascript/ql/lib/semmle/javascript/AST.qll index 0467847a9a04..0e6330605ba5 100644 --- a/javascript/ql/lib/semmle/javascript/AST.qll +++ b/javascript/ql/lib/semmle/javascript/AST.qll @@ -477,6 +477,8 @@ module AST { DataFlow::AnalyzedNode analyze() { result = DataFlow::valueNode(this).analyze() } /** Gets the data flow node associated with this program element. */ + overlay[caller] + pragma[inline] DataFlow::ValueNode flow() { result = DataFlow::valueNode(this) } /** diff --git a/javascript/ql/lib/semmle/javascript/Regexp.qll b/javascript/ql/lib/semmle/javascript/Regexp.qll index dba2c853008d..db779e600d67 100644 --- a/javascript/ql/lib/semmle/javascript/Regexp.qll +++ b/javascript/ql/lib/semmle/javascript/Regexp.qll @@ -1016,7 +1016,7 @@ overlay[global] pragma[inline] private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) { any(Comparison compare) - .hasOperands(value.getALocalUse().asExpr(), any(Expr e | e.analyze().getAType() = TTNumber())) + .hasOperands(value.getALocalUse().asExpr(), any(Expr e | canBeNumber(e.analyze()))) or value.flowsToExpr(any(ArithmeticExpr e).getAnOperand()) or @@ -1031,6 +1031,16 @@ private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) { ) } +bindingset[node] +overlay[global] +pragma[inline_late] +private predicate canBeString(DataFlow::AnalyzedNode node) { node.getAType() = TTString() } + +bindingset[node] +overlay[global] +pragma[inline_late] +private predicate canBeNumber(DataFlow::AnalyzedNode node) { node.getAType() = TTNumber() } + /** * Holds if `source` may be interpreted as a regular expression. */ @@ -1038,14 +1048,14 @@ overlay[global] cached predicate isInterpretedAsRegExp(DataFlow::Node source) { Stages::Taint::ref() and - source.analyze().getAType() = TTString() and + canBeString(source) and ( // The first argument to an invocation of `RegExp` (with or without `new`). source = DataFlow::globalVarRef("RegExp").getAnInvocation().getArgument(0) or // The argument of a call that coerces the argument to a regular expression. exists(DataFlow::MethodCallNode mce, string methodName | - mce.getReceiver().analyze().getAType() = TTString() and + canBeString(mce.getReceiver()) and mce.getMethodName() = methodName and not exists(Function func | func = mce.getACallee() | not isNativeStringMethod(func, methodName) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll index 9d4bda428b52..a5fb31df57e9 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll @@ -1431,6 +1431,7 @@ module DataFlow { * This predicate is only defined for expressions, properties, and for statements that declare * a function, a class, or a TypeScript namespace or enum. */ + pragma[nomagic] ValueNode valueNode(AstNode nd) { result.getAstNode() = nd } /** diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll b/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll index aec8c82247fc..e8b389e91ad5 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll @@ -45,7 +45,7 @@ module LazyCache { pragma[noopt] override DataFlow::Node getImportedModuleNode() { this instanceof LazyCacheImport and - result = this.flow() + result = DataFlow::valueNode(this) or exists(LazyCacheVariable variable, Expr base, PropAccess access, string localName | // To avoid recursion, this should not depend on `SourceNode`. @@ -54,7 +54,7 @@ module LazyCache { access.getBase() = base and localName = this.getLocalAlias() and access.getPropertyName() = localName and - result = access.flow() + result = DataFlow::valueNode(access) ) } } diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll index 68298c3fb554..d8460f7d729a 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll @@ -50,12 +50,18 @@ class ForOfLoopStep extends AdditionalFlowInternal { ) { exists(ForOfStmt stmt | pred = getSynthesizedNode(stmt, "for-of-map-key") and - contents.asSingleton().asArrayIndex() = 0 + contents = arrayIndex0() or pred = getSynthesizedNode(stmt, "for-of-map-value") and - contents.asSingleton().asArrayIndex() = 1 + contents = arrayIndex1() | succ = DataFlow::lvalueNode(stmt.getLValue()) ) } } + +pragma[nomagic] +private DataFlow::ContentSet arrayIndex0() { result.asSingleton().asArrayIndex() = 0 } + +pragma[nomagic] +private DataFlow::ContentSet arrayIndex1() { result.asSingleton().asArrayIndex() = 1 } From 4ef6f02786f9c3e13424ec40adc7c1ad02373b9d Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 22 Oct 2025 12:24:23 +0200 Subject: [PATCH 12/59] JS: Improve join orders related to getABooleanValue() --- .../ql/lib/semmle/javascript/dataflow/AbstractValues.qll | 1 + .../ql/lib/semmle/javascript/dataflow/TypeInference.qll | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll b/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll index 17908c0b67f1..c5d9993dbb75 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll @@ -59,6 +59,7 @@ class AbstractValue extends TAbstractValue { * Gets the Boolean value some concrete value represented by this * abstract value coerces to. */ + pragma[nomagic] abstract boolean getBooleanValue(); /** diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll index 32ad78eb2c6d..a5e686a90c25 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll @@ -92,10 +92,15 @@ class AnalyzedNode extends DataFlow::Node { PrimitiveType getAPrimitiveType() { result = this.getAValue().toPrimitive().getType() } /** Gets a Boolean value that this node evaluates to. */ + bindingset[this] + overlay[caller?] + pragma[inline_late] boolean getABooleanValue() { result = this.getAValue().getBooleanValue() } /** Gets the unique Boolean value that this node evaluates to, if any. */ - boolean getTheBooleanValue() { forex(boolean bv | bv = this.getABooleanValue() | result = bv) } + overlay[caller?] + pragma[inline] + boolean getTheBooleanValue() { result = unique( | | this.getABooleanValue()) } /** Gets the unique type inferred for this node, if any. */ InferredType getTheType() { result = unique(InferredType t | t = this.getAType()) } From 84e7101cff6f0feb8b29385a657c42df055761ac Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Oct 2025 09:35:40 +0100 Subject: [PATCH 13/59] JS: Remove obsolete overlay[global] annotations --- javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll | 1 - javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll | 1 - 2 files changed, 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll index a5fb31df57e9..d7fa6ba27623 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll @@ -102,7 +102,6 @@ module DataFlow { * Holds if this data flow node accesses the global variable `g`, either directly * or through the `window` object. */ - overlay[global] predicate accessesGlobal(string g) { globalVarRef(g).flowsTo(this) } /** Holds if this node may evaluate to the string `s`, possibly through local data flow. */ diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll index c4c7b1d7d18a..d4244ec3cbc6 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll @@ -791,7 +791,6 @@ ModuleImportNode dependencyModuleImport(Dependency dep) { * the given `path`, or accesses `m` as a member on a default or * namespace import from `path`. */ -overlay[global] DataFlow::SourceNode moduleMember(string path, string m) { result = moduleImport(path).getAPropertyRead(m) } From 7c9c9921d402b223fd26a13cf277cc6aa51b6d1c Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 3 Nov 2025 10:05:39 +0100 Subject: [PATCH 14/59] JS: Make isAssignedInUniqueFile global, as it should be --- javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll index 804542b0dc56..53e5a779a9b5 100644 --- a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll @@ -206,6 +206,7 @@ module AccessPath { * Holds if the global `accessPath` is only assigned to from one file, not counting * self-assignments. */ + overlay[global] predicate isAssignedInUniqueFile(string accessPath) { strictcount(File f | isAssignedInFile(accessPath, f)) = 1 } @@ -511,7 +512,7 @@ module AccessPath { /** * Holds if there is a step from `pred` to `succ` through an assignment to an access path. */ - overlay[caller] + overlay[caller?] pragma[inline] predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(string name, Root root | From 15cc9a23360ef547b14c03607d741478ff5c942a Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 3 Nov 2025 11:42:52 +0100 Subject: [PATCH 15/59] Sync ApiGraphModelsExtensions.qll --- .../frameworks/data/internal/ApiGraphModelsExtensions.qll | 2 ++ .../ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll | 2 ++ 2 files changed, 4 insertions(+) diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll index 4969da43be34..3f38c498f324 100644 --- a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll +++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll @@ -1,6 +1,8 @@ /** * Defines extensible predicates for contributing library models from data extensions. */ +overlay[local] +module; /** * Holds if the value at `(type, path)` should be seen as a flow diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll index 4969da43be34..3f38c498f324 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll @@ -1,6 +1,8 @@ /** * Defines extensible predicates for contributing library models from data extensions. */ +overlay[local] +module; /** * Holds if the value at `(type, path)` should be seen as a flow From b9c46367bb362c1588c1e1fe30fb4f7967a419c9 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 3 Nov 2025 11:43:16 +0100 Subject: [PATCH 16/59] Sync ApiGraphModels.qll --- .../semmle/python/frameworks/data/internal/ApiGraphModels.qll | 2 ++ .../lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll | 2 ++ 2 files changed, 4 insertions(+) diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll index c04a85487acf..80ec45a3cf17 100644 --- a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll +++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll @@ -62,6 +62,8 @@ * should be prefixed with a tilde character (`~`). For example, `~Bar` can be used to indicate that * the type is not intended to match a static type. */ +overlay[local?] +module; private import codeql.util.Unit private import ApiGraphModelsSpecific as Specific diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll index c04a85487acf..80ec45a3cf17 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll @@ -62,6 +62,8 @@ * should be prefixed with a tilde character (`~`). For example, `~Bar` can be used to indicate that * the type is not intended to match a static type. */ +overlay[local?] +module; private import codeql.util.Unit private import ApiGraphModelsSpecific as Specific From 7fcc357b965f82ba6c8aa0e548ef3a540d7d0c7e Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 7 Oct 2025 12:25:25 +0200 Subject: [PATCH 17/59] wp --- .../ql/lib/semmle/javascript/ApiGraphs2.qll | 220 ++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 javascript/ql/lib/semmle/javascript/ApiGraphs2.qll diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs2.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs2.qll new file mode 100644 index 000000000000..18624595e49b --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs2.qll @@ -0,0 +1,220 @@ +private import javascript +private import semmle.javascript.dataflow.internal.StepSummary + +private newtype TLabel = + MkMemberLabel(PropertyName prop) or + MkArgumentLabel(int n) { exists(any(DataFlow::InvokeNode i).getArgument(n)) } or + MkParameterLabel(int n) { exists(any(DataFlow::FunctionNode i).getParameter(n)) } + +class Label extends TLabel { + string asMember() { this = MkMemberLabel(result) } + + int asArgumentIndex() { this = MkArgumentLabel(result) } + + int asParameterIndex() { this = MkParameterLabel(result) } + + string toString() { + result = "Member[" + this.asMember() + "]" or + result = "Argument[" + this.asArgumentIndex() + "]" or + result = "Parameter[" + this.asParameterIndex() + "]" + } +} + +module API { + private class Node = DataFlow::Node; + + predicate useToUseStep(Node node1, Label label, Node node2) { + exists(DataFlow::PropRead read | + node1 = read.getBase() and + node2 = read and + label.asMember() = read.getPropertyName() + ) + } + + predicate defToDefStep(Node node1, Label label, Node node2) { + exists(DataFlow::PropWrite write | + node1 = write.getBase().getALocalSource() and + node2 = write.getRhs() and + label.asMember() = write.getPropertyName() + ) + } + + predicate defToUseStep(Node node1, Label label, Node node2) { + exists(DataFlow::FunctionNode fun, int i | + node1 = fun and + node2 = fun.getParameter(i) and + label.asParameterIndex() = i + ) + } + + predicate useToDefStep(Node node1, Label label, Node node2) { + exists(DataFlow::InvokeNode node, int i | + node1 = node.getCalleeNode() and + node2 = node.getArgument(i) and + label.asArgumentIndex() = i + ) + } + + signature module DeepFlowInputSig { + predicate isEntryPointUse(Node node); + + predicate isEntryPointDef(Node node); + + bindingset[node] + predicate shouldInclude(Node node); + } + + overlay[local?] + module DeepFlow { + private import S + + private predicate isUseNodeRoot(DataFlow::SourceNode node) { + isEntryPointUse(node) + or + useToUseStep(trackUse(_), _, node) and shouldInclude(node) + or + defToUseStep(trackDef(_), _, node) and shouldInclude(node) + } + + DataFlow::SourceNode trackUse(DataFlow::SourceNode node, DataFlow::TypeTracker t) { + isUseNodeRoot(node) and + result = node and + t.start() + or + exists(DataFlow::TypeTracker t2 | result = trackUse(node, t2).track(t2, t)) + } + + DataFlow::SourceNode trackUse(DataFlow::SourceNode node) { + result = trackUse(node, DataFlow::TypeTracker::end()) + } + + private predicate isDefNodeRoot(DataFlow::Node node) { + isEntryPointDef(node) + or + useToDefStep(trackUse(_), _, node) and shouldInclude(node) + or + defToDefStep(trackDef(_), _, node) and shouldInclude(node) + } + + DataFlow::SourceNode trackDef(DataFlow::Node node, DataFlow::TypeBackTracker t) { + isDefNodeRoot(node) and + result = node.getALocalSource() and + t.start() + or + exists(DataFlow::TypeBackTracker t2 | result = trackDef(node, t2).backtrack(t2, t)) + } + + DataFlow::SourceNode trackDef(DataFlow::Node node) { + result = trackDef(node, DataFlow::TypeBackTracker::end()) + } + } + + private module Input1 implements DeepFlowInputSig { + predicate isEntryPointUse(Node node) { + exists(Import imprt | + imprt.getImportedPathString().regexpMatch("[^./].*") and + node = imprt.getImportedModuleNode() + ) + } + + predicate isEntryPointDef(Node node) { + exists(PackageJson pkg | + not pkg.isPrivate() and + node = + [pkg.getMainModule().getAnExportedValue(_), pkg.getMainModule().getABulkExportedNode()] + ) + } + + bindingset[node] + predicate shouldInclude(Node node) { any() } + } + + private module DeepFlow1 = DeepFlow; + + overlay[local] + DataFlow::SourceNode trackUseLocal(DataFlow::SourceNode node) = + forceLocal(DeepFlow1::trackUse/1)(node, result) + + overlay[local] + DataFlow::SourceNode trackDefLocal(DataFlow::Node node) = + forceLocal(DeepFlow1::trackDef/1)(node, result) + + bindingset[node] + overlay[global] + pragma[inline_late] + private predicate isInOverlayChangedFile(DataFlow::Node node) { + overlayChangedFiles(node.getFile().getAbsolutePath()) + } + + predicate stepIntoOverlay(Node node1, Node node2, StepSummary summary) { + StepSummary::smallstep(node1, node2, summary) and + not isInOverlayChangedFile(node1) and + isInOverlayChangedFile(node2) + } + + predicate stepOutOfOverlay(Node node1, Node node2, StepSummary summary) { + StepSummary::smallstep(node1, node2, summary) and + isInOverlayChangedFile(node1) and + not isInOverlayChangedFile(node2) + } + + private module Input2 implements DeepFlowInputSig { + predicate isEntryPointUse(Node node) { + stepIntoOverlay(trackUseLocal(node).getALocalUse(), _, _) + } + + predicate isEntryPointDef(Node node) { stepOutOfOverlay(_, trackDefLocal(node), _) } + + predicate shouldInclude(Node node) { isInOverlayChangedFile(node) } + } + + private module DeepFlow2 = DeepFlow; + + DataFlow::SourceNode trackUseFinal(DataFlow::SourceNode node) { + result = DeepFlow1::trackUse(node) + or + result = DeepFlow2::trackUse(node) + } + + DataFlow::SourceNode trackDefFinal(DataFlow::Node node) { + result = DeepFlow1::trackDef(node) + or + result = DeepFlow2::trackDef(node) + } + + module Debug { + query DataFlow::SourceNode trackUseLostAfterForceLocal(DataFlow::SourceNode node) { + result = DeepFlow1::trackUse(node) and + not result = trackUseLocal(node) + } + + query DataFlow::SourceNode trackDefLostAfterForceLocal(DataFlow::Node node) { + result = DeepFlow1::trackDef(node) and + not result = trackDefLocal(node) + } + + query predicate trackUseSecondPass = DeepFlow2::trackUse/1; + + query predicate trackDefSecondPass = DeepFlow2::trackDef/1; + + query DataFlow::SourceNode trackUseLost(DataFlow::SourceNode node) { + result = DeepFlow1::trackUse(node) and + not result = trackUseFinal(node) + } + + query DataFlow::SourceNode trackDefLost(DataFlow::Node node) { + result = DeepFlow1::trackDef(node) and + not result = trackDefFinal(node) + } + + query DataFlow::SourceNode trackUseGained(DataFlow::SourceNode node) { + not result = DeepFlow1::trackUse(node) and + result = trackUseFinal(node) + } + + query DataFlow::SourceNode trackDefGained(DataFlow::Node node) { + not result = DeepFlow1::trackDef(node) and + result = trackDefFinal(node) + } + } +} From a6f3990cb8c9bcd738be5b5f4f47904606d725e8 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 12:03:57 +0200 Subject: [PATCH 18/59] JS: Convert boolean to a newtype --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 1a96e25b3b9f..5b22927b9d6b 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1043,7 +1043,7 @@ module API { // property reads exists(DataFlow::SourceNode src, DataFlow::SourceNode pred, string propDesc | use(base, src) and - pred = trackUseNode(src, false, 0, propDesc) and + pred = trackUseNode(src, Promisification::notPromisified(), 0, propDesc) and propertyRead(pred, propDesc, lbl, ref) and // `module.exports` is special: it is a use of a def-node, not a use-node, // so we want to exclude it here @@ -1253,6 +1253,26 @@ module API { private import semmle.javascript.dataflow.TypeTracking + private module Promisification { + private newtype TState = + /** Default statue; the tracked value has not been through any steps related to promisification. */ + TNotPromisified() or + /** The tracked value is a function that has been through promisification. */ + TPromisifiedFunction() + + class State extends TState { + string toString() { + this = TNotPromisified() and result = "not-promisified" + or + this = TPromisifiedFunction() and result = "promisified-function" + } + } + + State notPromisified() { result = TNotPromisified() } + + State promisifiedFunction() { result = TPromisifiedFunction() } + } + /** * Gets a data-flow node to which `nd`, which is a use of an API-graph node, flows. * @@ -1267,19 +1287,20 @@ module API { * and not necessarily the entire object. */ private DataFlow::SourceNode trackUseNode( - DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop, + DataFlow::SourceNode nd, Promisification::State promisified, int boundArgs, string prop, DataFlow::TypeTracker t ) { t.start() and use(_, nd) and result = nd and - promisified = false and + promisified = Promisification::notPromisified() and boundArgs = 0 and prop = "" or exists(Promisify::PromisifyCall promisify | - trackUseNode(nd, false, boundArgs, prop, t.continue()).flowsTo(promisify.getArgument(0)) and - promisified = true and + trackUseNode(nd, Promisification::notPromisified(), boundArgs, prop, t.continue()) + .flowsTo(promisify.getArgument(0)) and + promisified = Promisification::promisifiedFunction() and prop = "" and result = promisify ) @@ -1298,7 +1319,7 @@ module API { or exists(DataFlow::Node pred, string preprop | trackUseNode(nd, promisified, boundArgs, preprop, t.continue()).flowsTo(pred) and - promisified = false and + promisified = Promisification::notPromisified() and boundArgs = 0 and SharedTypeTrackingStep::loadStoreStep(pred, result, prop) | @@ -1319,7 +1340,8 @@ module API { */ pragma[noopt] private DataFlow::TypeTracker useStep( - DataFlow::Node nd, boolean promisified, int boundArgs, string prop, DataFlow::Node res + DataFlow::Node nd, Promisification::State promisified, int boundArgs, string prop, + DataFlow::Node res ) { exists(DataFlow::TypeTracker t, StepSummary summary, DataFlow::SourceNode prev | prev = trackUseNode(nd, promisified, boundArgs, prop, t) and @@ -1331,7 +1353,7 @@ module API { } private DataFlow::SourceNode trackUseNode( - DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop + DataFlow::SourceNode nd, Promisification::State promisified, int boundArgs, string prop ) { result = trackUseNode(nd, promisified, boundArgs, prop, DataFlow::TypeTracker::end()) } @@ -1341,7 +1363,7 @@ module API { */ cached DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { - result = trackUseNode(nd, false, 0, "") + result = trackUseNode(nd, Promisification::notPromisified(), 0, "") } private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) { From 39cba9e7763d62e3abcb155eb08554d122011f4a Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 12:14:21 +0200 Subject: [PATCH 19/59] WIP: Factor out Promisification state --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 5b22927b9d6b..2615b50b9b8e 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1133,6 +1133,14 @@ module API { // for fields and accessors, mark the reads as use-nodes decoratorPropEdge(base, lbl, ref.(DataFlow::PropRead)) ) + or + // awaiting the return value from a promisified function + exists(DataFlow::SourceNode src, DataFlow::SourceNode pred, string propDesc, int boundArgs | + use(base, src) and + pred = trackUseNode(src, Promisification::promisifiedReturnValue(boundArgs), 0, propDesc) and + awaitedStep(pred, ref) and + lbl = Label::parameter(boundArgs) + ) } /** Holds if `base` is a use-node that flows to the decorator expression of the given decorator. */ @@ -1258,19 +1266,31 @@ module API { /** Default statue; the tracked value has not been through any steps related to promisification. */ TNotPromisified() or /** The tracked value is a function that has been through promisification. */ - TPromisifiedFunction() + TPromisifiedFunction() or + /** The tracked value is returned from a call to a promisified function, i.e. it is a promise resolving the value that eventually gets passed to a callback. */ + TPromisifiedReturnValue(int callbackArgumentIndex) { callbackArgumentIndex = [0 .. 10] } class State extends TState { string toString() { this = TNotPromisified() and result = "not-promisified" or this = TPromisifiedFunction() and result = "promisified-function" + or + exists(int i | + this = TPromisifiedReturnValue(i) and result = "promisified-return-value(" + i + ")" + ) } } State notPromisified() { result = TNotPromisified() } State promisifiedFunction() { result = TPromisifiedFunction() } + + State promisifiedReturnValue(int i) { result = TPromisifiedReturnValue(i) } + } + + private predicate awaitedStep(DataFlow::Node node1, DataFlow::Node node2) { + StepSummary::smallstep(node1, node2, LoadStep(Promises::valueProp())) } /** @@ -1305,6 +1325,16 @@ module API { result = promisify ) or + exists(DataFlow::CallNode call, int bound | + call = + trackUseNode(nd, Promisification::promisifiedFunction(), bound, prop, t.continue()) + .getACall() and + promisified = Promisification::promisifiedReturnValue(bound + call.getNumArgument()) and + boundArgs = 0 and + result = call and + prop = "" + ) + or exists(DataFlow::PartialInvokeNode pin, DataFlow::Node pred, int predBoundArgs | trackUseNode(nd, promisified, predBoundArgs, prop, t.continue()).flowsTo(pred) and prop = "" and From f5d105c4027ea00bb5b61c7c5bce309f0a0778f3 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 12:14:36 +0200 Subject: [PATCH 20/59] Revert "WIP: Factor out Promisification state" This reverts commit 79d2b84ded59e4b6157326a39598d3a62680acb7. --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 2615b50b9b8e..5b22927b9d6b 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1133,14 +1133,6 @@ module API { // for fields and accessors, mark the reads as use-nodes decoratorPropEdge(base, lbl, ref.(DataFlow::PropRead)) ) - or - // awaiting the return value from a promisified function - exists(DataFlow::SourceNode src, DataFlow::SourceNode pred, string propDesc, int boundArgs | - use(base, src) and - pred = trackUseNode(src, Promisification::promisifiedReturnValue(boundArgs), 0, propDesc) and - awaitedStep(pred, ref) and - lbl = Label::parameter(boundArgs) - ) } /** Holds if `base` is a use-node that flows to the decorator expression of the given decorator. */ @@ -1266,31 +1258,19 @@ module API { /** Default statue; the tracked value has not been through any steps related to promisification. */ TNotPromisified() or /** The tracked value is a function that has been through promisification. */ - TPromisifiedFunction() or - /** The tracked value is returned from a call to a promisified function, i.e. it is a promise resolving the value that eventually gets passed to a callback. */ - TPromisifiedReturnValue(int callbackArgumentIndex) { callbackArgumentIndex = [0 .. 10] } + TPromisifiedFunction() class State extends TState { string toString() { this = TNotPromisified() and result = "not-promisified" or this = TPromisifiedFunction() and result = "promisified-function" - or - exists(int i | - this = TPromisifiedReturnValue(i) and result = "promisified-return-value(" + i + ")" - ) } } State notPromisified() { result = TNotPromisified() } State promisifiedFunction() { result = TPromisifiedFunction() } - - State promisifiedReturnValue(int i) { result = TPromisifiedReturnValue(i) } - } - - private predicate awaitedStep(DataFlow::Node node1, DataFlow::Node node2) { - StepSummary::smallstep(node1, node2, LoadStep(Promises::valueProp())) } /** @@ -1325,16 +1305,6 @@ module API { result = promisify ) or - exists(DataFlow::CallNode call, int bound | - call = - trackUseNode(nd, Promisification::promisifiedFunction(), bound, prop, t.continue()) - .getACall() and - promisified = Promisification::promisifiedReturnValue(bound + call.getNumArgument()) and - boundArgs = 0 and - result = call and - prop = "" - ) - or exists(DataFlow::PartialInvokeNode pin, DataFlow::Node pred, int predBoundArgs | trackUseNode(nd, promisified, predBoundArgs, prop, t.continue()).flowsTo(pred) and prop = "" and From f0f93c3ad14527cf8258a7d11d1189bdfb5aacc5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 12:14:41 +0200 Subject: [PATCH 21/59] Revert "JS: Convert boolean to a newtype" This reverts commit bac3951256e813f9d2dedfc273e084093b816823. --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 40 +++++-------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 5b22927b9d6b..1a96e25b3b9f 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1043,7 +1043,7 @@ module API { // property reads exists(DataFlow::SourceNode src, DataFlow::SourceNode pred, string propDesc | use(base, src) and - pred = trackUseNode(src, Promisification::notPromisified(), 0, propDesc) and + pred = trackUseNode(src, false, 0, propDesc) and propertyRead(pred, propDesc, lbl, ref) and // `module.exports` is special: it is a use of a def-node, not a use-node, // so we want to exclude it here @@ -1253,26 +1253,6 @@ module API { private import semmle.javascript.dataflow.TypeTracking - private module Promisification { - private newtype TState = - /** Default statue; the tracked value has not been through any steps related to promisification. */ - TNotPromisified() or - /** The tracked value is a function that has been through promisification. */ - TPromisifiedFunction() - - class State extends TState { - string toString() { - this = TNotPromisified() and result = "not-promisified" - or - this = TPromisifiedFunction() and result = "promisified-function" - } - } - - State notPromisified() { result = TNotPromisified() } - - State promisifiedFunction() { result = TPromisifiedFunction() } - } - /** * Gets a data-flow node to which `nd`, which is a use of an API-graph node, flows. * @@ -1287,20 +1267,19 @@ module API { * and not necessarily the entire object. */ private DataFlow::SourceNode trackUseNode( - DataFlow::SourceNode nd, Promisification::State promisified, int boundArgs, string prop, + DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop, DataFlow::TypeTracker t ) { t.start() and use(_, nd) and result = nd and - promisified = Promisification::notPromisified() and + promisified = false and boundArgs = 0 and prop = "" or exists(Promisify::PromisifyCall promisify | - trackUseNode(nd, Promisification::notPromisified(), boundArgs, prop, t.continue()) - .flowsTo(promisify.getArgument(0)) and - promisified = Promisification::promisifiedFunction() and + trackUseNode(nd, false, boundArgs, prop, t.continue()).flowsTo(promisify.getArgument(0)) and + promisified = true and prop = "" and result = promisify ) @@ -1319,7 +1298,7 @@ module API { or exists(DataFlow::Node pred, string preprop | trackUseNode(nd, promisified, boundArgs, preprop, t.continue()).flowsTo(pred) and - promisified = Promisification::notPromisified() and + promisified = false and boundArgs = 0 and SharedTypeTrackingStep::loadStoreStep(pred, result, prop) | @@ -1340,8 +1319,7 @@ module API { */ pragma[noopt] private DataFlow::TypeTracker useStep( - DataFlow::Node nd, Promisification::State promisified, int boundArgs, string prop, - DataFlow::Node res + DataFlow::Node nd, boolean promisified, int boundArgs, string prop, DataFlow::Node res ) { exists(DataFlow::TypeTracker t, StepSummary summary, DataFlow::SourceNode prev | prev = trackUseNode(nd, promisified, boundArgs, prop, t) and @@ -1353,7 +1331,7 @@ module API { } private DataFlow::SourceNode trackUseNode( - DataFlow::SourceNode nd, Promisification::State promisified, int boundArgs, string prop + DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop ) { result = trackUseNode(nd, promisified, boundArgs, prop, DataFlow::TypeTracker::end()) } @@ -1363,7 +1341,7 @@ module API { */ cached DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { - result = trackUseNode(nd, Promisification::notPromisified(), 0, "") + result = trackUseNode(nd, false, 0, "") } private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) { From 6b423e5424d33eda9f985397e5e5d6d55ff11090 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 13:01:14 +0200 Subject: [PATCH 22/59] JS: Make MkSyntheticCallbackArg() independent of trackUseNode --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 1a96e25b3b9f..e1c5fe192b71 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -545,7 +545,7 @@ module API { this = Impl::MkClassInstance(result) or this = Impl::MkUse(result) or this = Impl::MkDef(result) or - this = Impl::MkSyntheticCallbackArg(_, _, result) + this = Impl::MkSyntheticCallbackArg(result) } /** @@ -760,9 +760,7 @@ module API { MkTypeUse(string moduleName, string exportName) { any(TypeAnnotation n).hasUnderlyingType(moduleName, exportName) } or - MkSyntheticCallbackArg(DataFlow::Node src, int bound, DataFlow::InvokeNode nd) { - trackUseNode(src, true, bound, "").flowsTo(nd.getCalleeNode()) - } + MkSyntheticCallbackArg(DataFlow::InvokeNode nd) private predicate needsDefNode(DataFlow::ClassNode cls) { hasSemantics(cls) and @@ -1110,7 +1108,7 @@ module API { ) or exists(DataFlow::InvokeNode call | - base = MkSyntheticCallbackArg(_, _, call) and + base = MkSyntheticCallbackArg(call) and lbl = Label::parameter(1) and ref = awaited(call) ) @@ -1399,7 +1397,7 @@ module API { private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) { t.startInPromise() and - exists(MkSyntheticCallbackArg(_, _, call)) and + trackUseNode(_, true, _, "").flowsTo(call.getCalleeNode()) and result = call or exists(DataFlow::TypeTracker t2 | result = awaited(call, t2).track(t2, t)) @@ -1494,7 +1492,8 @@ module API { DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { exists(DataFlow::SourceNode src | Impl::use(callee, src) and - succ = Impl::MkSyntheticCallbackArg(src, bound, result) + trackUseNode(src, true, bound, "").flowsTo(result.getCalleeNode()) and + succ = Impl::MkSyntheticCallbackArg(result) ) } } From 0a181beb7b82261fde1c6f2cd80e89b259fa14a1 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 13:28:55 +0200 Subject: [PATCH 23/59] JS: Make other node types not depend on tracking predicates --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index e1c5fe192b71..b1e7afe3a8fd 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -753,9 +753,25 @@ module API { or any(TypeAnnotation n).hasUnderlyingType(m, _) } or - MkClassInstance(DataFlow::ClassNode cls) { needsDefNode(cls) } or - MkDef(DataFlow::Node nd) { rhs(_, _, nd) } or - MkUse(DataFlow::Node nd) { use(_, _, nd) } or + MkClassInstance(DataFlow::ClassNode cls) or + MkDef(DataFlow::Node nd) { + nd = any(DataFlow::PropWrite w).getRhs() + or + nd = any(DataFlow::FunctionNode fn).getReturnNode() + or + nd = any(DataFlow::FunctionNode fn).getAReturn() + or + nd = any(Module m).getAnExportedValue(_) + or + nd = any(Module m).getABulkExportedNode() + or + nd = any(DataFlow::InvokeNode i).getAnArgument() + or + nd = any(DataFlow::InvokeNode i).getASpreadArgument() + or + nd = any(EntryPoint e).getASink() + } or + MkUse(DataFlow::Node nd) { nd instanceof DataFlow::SourceNode } or /** A use of a TypeScript type. */ MkTypeUse(string moduleName, string exportName) { any(TypeAnnotation n).hasUnderlyingType(moduleName, exportName) @@ -984,6 +1000,7 @@ module API { predicate rhs(TApiNode nd, DataFlow::Node rhs) { exists(string m | nd = MkModuleExport(m) | exports(m, rhs)) or + rhs(_, _, rhs) and nd = MkDef(rhs) } @@ -1246,6 +1263,7 @@ module API { ref = cls.(DataFlow::ClassNode).getAPrototypeReference() ) or + use(_, _, ref) and nd = MkUse(ref) } From 73531e55e5bcbcfbf3dac0fba80eade886c988b3 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 13:29:14 +0200 Subject: [PATCH 24/59] JS: Remove unused predicate --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index b1e7afe3a8fd..dd2d742b39c3 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -778,17 +778,6 @@ module API { } or MkSyntheticCallbackArg(DataFlow::InvokeNode nd) - private predicate needsDefNode(DataFlow::ClassNode cls) { - hasSemantics(cls) and - ( - cls = trackDefNode(_) - or - cls.getAnInstanceReference() = trackDefNode(_) - or - needsDefNode(cls.getADirectSubClass()) - ) - } - class TDef = MkModuleDef or TNonModuleDef; class TNonModuleDef = MkModuleExport or MkClassInstance or MkDef or MkSyntheticCallbackArg; From 4511f7cc7095f1bb266812823aae1860a2447ab3 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 13:46:53 +0200 Subject: [PATCH 25/59] JS: Make use() and rhs() uncached and private --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index dd2d742b39c3..a1c95402acbf 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -798,8 +798,7 @@ module API { * Holds if `rhs` is the right-hand side of a definition of a node that should have an * incoming edge from `base` labeled `lbl` in the API graph. */ - cached - predicate rhs(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { + private predicate rhs(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { hasSemantics(rhs) and ( base = MkRoot() and From cf09daa2c3a803bb6b4c05067a4186ac16fce50b Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 13:55:38 +0200 Subject: [PATCH 26/59] JS: Wrap in a module Simply wraps everything in 'cached private module Stage {}' and adds 'import Stage'. The diff is large because of indentation changes. --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 1219 ++++++++--------- 1 file changed, 604 insertions(+), 615 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index a1c95402acbf..093006d457e2 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -794,693 +794,695 @@ module API { hasSemantics(imp) } - /** - * Holds if `rhs` is the right-hand side of a definition of a node that should have an - * incoming edge from `base` labeled `lbl` in the API graph. - */ - private predicate rhs(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { - hasSemantics(rhs) and - ( - base = MkRoot() and - exists(EntryPoint e | - lbl = Label::entryPoint(e) and - rhs = e.getASink() - ) - or - exists(string m, string prop | - base = MkModuleExport(m) and - lbl = Label::member(prop) and - exports(m, prop, rhs) - ) - or - exists(DataFlow::Node def, DataFlow::SourceNode pred | - rhs(base, def) and pred = trackDefNode(def) - | - // from `x` to a definition of `x.prop` - exists(DataFlow::PropWrite pw | pw = pred.getAPropertyWrite() | - lbl = Label::memberFromRef(pw) and - rhs = pw.getRhs() + cached + private module Stage { + /** + * Holds if `rhs` is the right-hand side of a definition of a node that should have an + * incoming edge from `base` labeled `lbl` in the API graph. + */ + private predicate rhs(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { + hasSemantics(rhs) and + ( + base = MkRoot() and + exists(EntryPoint e | + lbl = Label::entryPoint(e) and + rhs = e.getASink() ) or - // special case: from `require('m')` to an export of `prop` in `m` - exists(Import imp, Module m, string prop | - pred = imp.getImportedModuleNodeStrict() and - m = imp.getImportedModule() and + exists(string m, string prop | + base = MkModuleExport(m) and lbl = Label::member(prop) and - rhs = m.getAnExportedValue(prop) + exports(m, prop, rhs) ) or - // In general, turn store steps into member steps for def-nodes - exists(string prop | - PreCallGraphStep::storeStep(rhs, pred, prop) and - lbl = Label::member(prop) and - not DataFlow::PseudoProperties::isPseudoProperty(prop) + exists(DataFlow::Node def, DataFlow::SourceNode pred | + rhs(base, def) and pred = trackDefNode(def) + | + // from `x` to a definition of `x.prop` + exists(DataFlow::PropWrite pw | pw = pred.getAPropertyWrite() | + lbl = Label::memberFromRef(pw) and + rhs = pw.getRhs() + ) + or + // special case: from `require('m')` to an export of `prop` in `m` + exists(Import imp, Module m, string prop | + pred = imp.getImportedModuleNodeStrict() and + m = imp.getImportedModule() and + lbl = Label::member(prop) and + rhs = m.getAnExportedValue(prop) + ) + or + // In general, turn store steps into member steps for def-nodes + exists(string prop | + PreCallGraphStep::storeStep(rhs, pred, prop) and + lbl = Label::member(prop) and + not DataFlow::PseudoProperties::isPseudoProperty(prop) + ) + or + exists(DataFlow::ContentSet contents | + SummaryTypeTracker::basicStoreStep(rhs, pred.getALocalUse(), contents) and + lbl = Label::content(contents.getAStoreContent()) + ) + or + exists(DataFlow::FunctionNode fn | + fn = pred and + lbl = Label::return() + | + if fn.getFunction().isAsync() then rhs = fn.getReturnNode() else rhs = fn.getAReturn() + ) + or + lbl = Label::promised() and + SharedTypeTrackingStep::storeStep(rhs, pred, Promises::valueProp()) + or + lbl = Label::promisedError() and + SharedTypeTrackingStep::storeStep(rhs, pred, Promises::errorProp()) + or + // The return-value of a getter G counts as a definition of property G + // (Ordinary methods and properties are handled as PropWrite nodes) + exists(string name | lbl = Label::member(name) | + rhs = pred.(DataFlow::ObjectLiteralNode).getPropertyGetter(name).getAReturn() + or + rhs = + pred.(DataFlow::ClassNode) + .getStaticMember(name, DataFlow::MemberKind::getter()) + .getAReturn() + ) + or + // Handle rest parameters escaping into external code. For example: + // + // function foo(...rest) { + // externalFunc(rest); + // } + // + // Here, 'rest' reaches a def-node at the call to externalFunc, so we need to ensure + // the arguments passed to 'foo' are stored in the 'rest' array. + exists(Function fun, DataFlow::InvokeNode invoke, int argIndex, Parameter rest | + fun.getRestParameter() = rest and + rest.flow() = pred and + invoke.getACallee() = fun and + invoke.getArgument(argIndex) = rhs and + argIndex >= rest.getIndex() and + lbl = Label::member((argIndex - rest.getIndex()).toString()) + ) ) or - exists(DataFlow::ContentSet contents | - SummaryTypeTracker::basicStoreStep(rhs, pred.getALocalUse(), contents) and - lbl = Label::content(contents.getAStoreContent()) + exists(DataFlow::ClassNode cls, string name | + base = MkClassInstance(cls) and + lbl = Label::member(name) + | + rhs = cls.getInstanceMethod(name) + or + rhs = cls.getInstanceMember(name, DataFlow::MemberKind::getter()).getAReturn() ) or - exists(DataFlow::FunctionNode fn | - fn = pred and - lbl = Label::return() + exists(DataFlow::FunctionNode f | + f.getFunction().isAsync() and + base = MkDef(f.getReturnNode()) | - if fn.getFunction().isAsync() then rhs = fn.getReturnNode() else rhs = fn.getAReturn() + lbl = Label::promised() and + rhs = f.getAReturn() + or + lbl = Label::promisedError() and + rhs = f.getExceptionalReturn() ) or - lbl = Label::promised() and - SharedTypeTrackingStep::storeStep(rhs, pred, Promises::valueProp()) - or - lbl = Label::promisedError() and - SharedTypeTrackingStep::storeStep(rhs, pred, Promises::errorProp()) - or - // The return-value of a getter G counts as a definition of property G - // (Ordinary methods and properties are handled as PropWrite nodes) - exists(string name | lbl = Label::member(name) | - rhs = pred.(DataFlow::ObjectLiteralNode).getPropertyGetter(name).getAReturn() + exists(int i | argumentPassing(base, i, rhs) | + lbl = Label::parameter(i) or - rhs = - pred.(DataFlow::ClassNode) - .getStaticMember(name, DataFlow::MemberKind::getter()) - .getAReturn() + i = -1 and lbl = Label::receiver() ) or - // Handle rest parameters escaping into external code. For example: - // - // function foo(...rest) { - // externalFunc(rest); - // } - // - // Here, 'rest' reaches a def-node at the call to externalFunc, so we need to ensure - // the arguments passed to 'foo' are stored in the 'rest' array. - exists(Function fun, DataFlow::InvokeNode invoke, int argIndex, Parameter rest | - fun.getRestParameter() = rest and - rest.flow() = pred and - invoke.getACallee() = fun and - invoke.getArgument(argIndex) = rhs and - argIndex >= rest.getIndex() and - lbl = Label::member((argIndex - rest.getIndex()).toString()) + exists(int i | + spreadArgumentPassing(base, i, rhs) and + lbl = Label::spreadArgument(i) ) - ) - or - exists(DataFlow::ClassNode cls, string name | - base = MkClassInstance(cls) and - lbl = Label::member(name) - | - rhs = cls.getInstanceMethod(name) - or - rhs = cls.getInstanceMember(name, DataFlow::MemberKind::getter()).getAReturn() - ) - or - exists(DataFlow::FunctionNode f | - f.getFunction().isAsync() and - base = MkDef(f.getReturnNode()) - | - lbl = Label::promised() and - rhs = f.getAReturn() or - lbl = Label::promisedError() and - rhs = f.getExceptionalReturn() + exists(DataFlow::SourceNode src, DataFlow::PropWrite pw | + use(base, src) and pw = trackUseNode(src).getAPropertyWrite() and rhs = pw.getRhs() + | + lbl = Label::memberFromRef(pw) + ) ) or - exists(int i | argumentPassing(base, i, rhs) | - lbl = Label::parameter(i) - or - i = -1 and lbl = Label::receiver() - ) + decoratorDualEdge(base, lbl, rhs) or - exists(int i | - spreadArgumentPassing(base, i, rhs) and - lbl = Label::spreadArgument(i) - ) + decoratorRhsEdge(base, lbl, rhs) or - exists(DataFlow::SourceNode src, DataFlow::PropWrite pw | - use(base, src) and pw = trackUseNode(src).getAPropertyWrite() and rhs = pw.getRhs() - | - lbl = Label::memberFromRef(pw) + exists(DataFlow::PropWrite write | + decoratorPropEdge(base, lbl, write) and + rhs = write.getRhs() ) - ) - or - decoratorDualEdge(base, lbl, rhs) - or - decoratorRhsEdge(base, lbl, rhs) - or - exists(DataFlow::PropWrite write | - decoratorPropEdge(base, lbl, write) and - rhs = write.getRhs() - ) - } + } - /** - * Holds if `arg` is passed as the `i`th argument to a use of `base`, either by means of a - * full invocation, or in a partial function application. - * - * The receiver is considered to be argument -1. - */ - private predicate argumentPassing(TApiNode base, int i, DataFlow::Node arg) { - exists(DataFlow::Node use, DataFlow::SourceNode pred, int bound | - use(base, use) and pred = trackUseNode(use, _, bound, "") - | - arg = pred.getAnInvocation().getArgument(i - bound) - or - arg = pred.getACall().getReceiver() and - bound = 0 and - i = -1 - or - exists(DataFlow::PartialInvokeNode pin, DataFlow::Node callback | pred.flowsTo(callback) | - pin.isPartialArgument(callback, arg, i - bound) + /** + * Holds if `arg` is passed as the `i`th argument to a use of `base`, either by means of a + * full invocation, or in a partial function application. + * + * The receiver is considered to be argument -1. + */ + private predicate argumentPassing(TApiNode base, int i, DataFlow::Node arg) { + exists(DataFlow::Node use, DataFlow::SourceNode pred, int bound | + use(base, use) and pred = trackUseNode(use, _, bound, "") + | + arg = pred.getAnInvocation().getArgument(i - bound) or - arg = pin.getBoundReceiver(callback) and + arg = pred.getACall().getReceiver() and bound = 0 and i = -1 + or + exists(DataFlow::PartialInvokeNode pin, DataFlow::Node callback | pred.flowsTo(callback) | + pin.isPartialArgument(callback, arg, i - bound) + or + arg = pin.getBoundReceiver(callback) and + bound = 0 and + i = -1 + ) ) - ) - } - - pragma[nomagic] - private int firstSpreadIndex(InvokeExpr expr) { - result = min(int i | expr.getArgument(i) instanceof SpreadElement) - } + } - pragma[nomagic] - private InvokeExpr getAnInvocationWithSpread(DataFlow::SourceNode node, int i) { - result = node.getAnInvocation().asExpr() and - i = firstSpreadIndex(result) - } + pragma[nomagic] + private int firstSpreadIndex(InvokeExpr expr) { + result = min(int i | expr.getArgument(i) instanceof SpreadElement) + } - private predicate spreadArgumentPassing(TApiNode base, int i, DataFlow::Node spreadArray) { - exists( - DataFlow::Node use, DataFlow::SourceNode pred, int bound, InvokeExpr invoke, int spreadPos - | - use(base, use) and - pred = trackUseNode(use, _, bound, "") and - invoke = getAnInvocationWithSpread(pred, spreadPos) and - spreadArray = invoke.getArgument(spreadPos).(SpreadElement).getOperand().flow() and - i = bound + spreadPos - ) - } + pragma[nomagic] + private InvokeExpr getAnInvocationWithSpread(DataFlow::SourceNode node, int i) { + result = node.getAnInvocation().asExpr() and + i = firstSpreadIndex(result) + } - /** - * Holds if `rhs` is the right-hand side of a definition of node `nd`. - */ - cached - predicate rhs(TApiNode nd, DataFlow::Node rhs) { - exists(string m | nd = MkModuleExport(m) | exports(m, rhs)) - or - rhs(_, _, rhs) and - nd = MkDef(rhs) - } + private predicate spreadArgumentPassing(TApiNode base, int i, DataFlow::Node spreadArray) { + exists( + DataFlow::Node use, DataFlow::SourceNode pred, int bound, InvokeExpr invoke, int spreadPos + | + use(base, use) and + pred = trackUseNode(use, _, bound, "") and + invoke = getAnInvocationWithSpread(pred, spreadPos) and + spreadArray = invoke.getArgument(spreadPos).(SpreadElement).getOperand().flow() and + i = bound + spreadPos + ) + } - /** - * Holds if `ref` is a read of a property described by `lbl` on `pred`, and - * `propDesc` is compatible with that property, meaning it is either the - * name of the property itself or the empty string. - */ - pragma[noinline] - private predicate propertyRead( - DataFlow::SourceNode pred, string propDesc, Label::ApiLabel lbl, DataFlow::Node ref - ) { - ref = pred.getAPropertyRead() and - lbl = Label::memberFromRef(ref) and - ( - lbl = Label::member(propDesc) + /** + * Holds if `rhs` is the right-hand side of a definition of node `nd`. + */ + cached + predicate rhs(TApiNode nd, DataFlow::Node rhs) { + exists(string m | nd = MkModuleExport(m) | exports(m, rhs)) or - propDesc = "" - ) - or - SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::valueProp()) and - lbl = Label::promised() and - (propDesc = Promises::valueProp() or propDesc = "") - or - SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::errorProp()) and - lbl = Label::promisedError() and - (propDesc = Promises::errorProp() or propDesc = "") - } - - pragma[nomagic] - private DataFlow::ClassNode getALocalSubclass(DataFlow::SourceNode node) { - result.getASuperClassNode().getALocalSource() = node - } - - bindingset[node] - pragma[inline_late] - private DataFlow::ClassNode getALocalSubclassFwd(DataFlow::SourceNode node) { - result = getALocalSubclass(node) - } + rhs(_, _, rhs) and + nd = MkDef(rhs) + } - /** - * Holds if `ref` is a use of a node that should have an incoming edge from `base` labeled - * `lbl` in the API graph. - */ - cached - predicate use(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { - hasSemantics(ref) and - ( - base = MkRoot() and - exists(EntryPoint e | - lbl = Label::entryPoint(e) and - ref = e.getASource() + /** + * Holds if `ref` is a read of a property described by `lbl` on `pred`, and + * `propDesc` is compatible with that property, meaning it is either the + * name of the property itself or the empty string. + */ + pragma[noinline] + private predicate propertyRead( + DataFlow::SourceNode pred, string propDesc, Label::ApiLabel lbl, DataFlow::Node ref + ) { + ref = pred.getAPropertyRead() and + lbl = Label::memberFromRef(ref) and + ( + lbl = Label::member(propDesc) + or + propDesc = "" ) or - // property reads - exists(DataFlow::SourceNode src, DataFlow::SourceNode pred, string propDesc | - use(base, src) and - pred = trackUseNode(src, false, 0, propDesc) and - propertyRead(pred, propDesc, lbl, ref) and - // `module.exports` is special: it is a use of a def-node, not a use-node, - // so we want to exclude it here - (base instanceof TNonModuleDef or base instanceof TUse) - ) + SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::valueProp()) and + lbl = Label::promised() and + (propDesc = Promises::valueProp() or propDesc = "") or - exists(DataFlow::SourceNode src, DataFlow::SourceNode pred | - use(base, src) and pred = trackUseNode(src) - | - lbl = Label::instance() and - ref = pred.getAnInstantiation() - or - lbl = Label::return() and - ref = pred.getAnInvocation() + SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::errorProp()) and + lbl = Label::promisedError() and + (propDesc = Promises::errorProp() or propDesc = "") + } + + pragma[nomagic] + private DataFlow::ClassNode getALocalSubclass(DataFlow::SourceNode node) { + result.getASuperClassNode().getALocalSource() = node + } + + bindingset[node] + pragma[inline_late] + private DataFlow::ClassNode getALocalSubclassFwd(DataFlow::SourceNode node) { + result = getALocalSubclass(node) + } + + /** + * Holds if `ref` is a use of a node that should have an incoming edge from `base` labeled + * `lbl` in the API graph. + */ + private predicate use(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { + hasSemantics(ref) and + ( + base = MkRoot() and + exists(EntryPoint e | + lbl = Label::entryPoint(e) and + ref = e.getASource() + ) or - lbl = Label::forwardingFunction() and - DataFlow::functionForwardingStep(pred.getALocalUse(), ref) + // property reads + exists(DataFlow::SourceNode src, DataFlow::SourceNode pred, string propDesc | + use(base, src) and + pred = trackUseNode(src, false, 0, propDesc) and + propertyRead(pred, propDesc, lbl, ref) and + // `module.exports` is special: it is a use of a def-node, not a use-node, + // so we want to exclude it here + (base instanceof TNonModuleDef or base instanceof TUse) + ) or - exists(DataFlow::ClassNode cls | + exists(DataFlow::SourceNode src, DataFlow::SourceNode pred | + use(base, src) and pred = trackUseNode(src) + | lbl = Label::instance() and - cls = getALocalSubclassFwd(pred).getADirectSubClass*() + ref = pred.getAnInstantiation() + or + lbl = Label::return() and + ref = pred.getAnInvocation() + or + lbl = Label::forwardingFunction() and + DataFlow::functionForwardingStep(pred.getALocalUse(), ref) + or + exists(DataFlow::ClassNode cls | + lbl = Label::instance() and + cls = getALocalSubclassFwd(pred).getADirectSubClass*() + | + ref = cls.getAReceiverNode() + or + ref = cls.getAClassReference().getAnInstantiation() + ) + or + exists(string prop | + PreCallGraphStep::loadStep(pred.getALocalUse(), ref, prop) and + lbl = Label::member(prop) and + // avoid generating member edges like "$arrayElement$" + not DataFlow::PseudoProperties::isPseudoProperty(prop) + ) + or + exists(DataFlow::ContentSet contents | + SummaryTypeTracker::basicLoadStep(pred.getALocalUse(), ref, contents) and + lbl = Label::content(contents.getAStoreContent()) + ) + ) + or + exists(DataFlow::Node def, DataFlow::FunctionNode fn | + rhs(base, def) and fn = trackDefNode(def) | - ref = cls.getAReceiverNode() + exists(int i | + lbl = Label::parameter(i) and + ref = fn.getParameter(i) + ) or - ref = cls.getAClassReference().getAnInstantiation() + lbl = Label::receiver() and + ref = fn.getReceiver() ) or - exists(string prop | - PreCallGraphStep::loadStep(pred.getALocalUse(), ref, prop) and - lbl = Label::member(prop) and - // avoid generating member edges like "$arrayElement$" - not DataFlow::PseudoProperties::isPseudoProperty(prop) + exists(DataFlow::Node def, DataFlow::ClassNode cls, int i | + rhs(base, def) and cls = trackDefNode(def) + | + lbl = Label::parameter(i) and + ref = cls.getConstructor().getParameter(i) + ) + or + exists(string moduleName, string exportName | + base = MkTypeUse(moduleName, exportName) and + lbl = Label::instance() and + ref.(DataFlow::SourceNode).hasUnderlyingType(moduleName, exportName) ) or - exists(DataFlow::ContentSet contents | - SummaryTypeTracker::basicLoadStep(pred.getALocalUse(), ref, contents) and - lbl = Label::content(contents.getAStoreContent()) + exists(DataFlow::InvokeNode call | + base = MkSyntheticCallbackArg(call) and + lbl = Label::parameter(1) and + ref = awaited(call) ) + or + decoratorDualEdge(base, lbl, ref) + or + decoratorUseEdge(base, lbl, ref) + or + // for fields and accessors, mark the reads as use-nodes + decoratorPropEdge(base, lbl, ref.(DataFlow::PropRead)) + ) + } + + /** Holds if `base` is a use-node that flows to the decorator expression of the given decorator. */ + pragma[nomagic] + private predicate useNodeFlowsToDecorator(TApiNode base, Decorator decorator) { + exists(DataFlow::SourceNode decoratorSrc | + use(base, decoratorSrc) and + trackUseNode(decoratorSrc).flowsToExpr(decorator.getExpression()) + ) + } + + /** + * Holds if `ref` corresponds to both a use and def-node that should have an incoming edge from `base` labelled `lbl`. + * + * This happens because the decorated value escapes into the decorator function, and is then replaced + * by the function's return value. In the JS analysis we generally assume decorators return their input, + * but library models may want to find the return value. + */ + private predicate decoratorDualEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { + exists(ClassDefinition cls | + useNodeFlowsToDecorator(base, cls.getADecorator()) and + lbl = Label::decoratedClass() and + ref = DataFlow::valueNode(cls) ) or - exists(DataFlow::Node def, DataFlow::FunctionNode fn | - rhs(base, def) and fn = trackDefNode(def) + exists(MethodDefinition method | + useNodeFlowsToDecorator(base, method.getADecorator()) and + not method instanceof AccessorMethodDefinition and + lbl = Label::decoratedMember() and + ref = DataFlow::valueNode(method.getBody()) + ) + } + + /** Holds if `ref` is a use that should have an incoming edge from `base` labelled `lbl`, induced by a decorator. */ + private predicate decoratorUseEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { + exists(SetterMethodDefinition accessor | + useNodeFlowsToDecorator(base, + [accessor.getADecorator(), accessor.getCorrespondingGetter().getADecorator()]) and + lbl = Label::decoratedMember() and + ref = DataFlow::parameterNode(accessor.getBody().getParameter(0)) + ) + or + exists(Parameter param | + useNodeFlowsToDecorator(base, param.getADecorator()) and + lbl = Label::decoratedParameter() and + ref = DataFlow::parameterNode(param) + ) + } + + /** Holds if `rhs` is a def node that should have an incoming edge from `base` labelled `lbl`, induced by a decorator. */ + private predicate decoratorRhsEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { + exists(GetterMethodDefinition accessor | + useNodeFlowsToDecorator(base, + [accessor.getADecorator(), accessor.getCorrespondingSetter().getADecorator()]) and + lbl = Label::decoratedMember() and + rhs = DataFlow::valueNode(accessor.getBody().getAReturnedExpr()) + ) + } + + /** + * Holds if `ref` is a reference to a field/accessor that should have en incoming edge from base labelled `lbl`. + * + * Since fields do not have their own data-flow nodes, we generate a node for each read or write. + * For property writes, the right-hand side becomes a def-node and property reads become use-nodes. + * + * For accessors this predicate computes each use of the accessor. + * The return value inside the accessor is computed by the `decoratorRhsEdge` predicate. + */ + private predicate decoratorPropEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::PropRef ref) { + exists(MemberDefinition fieldLike, DataFlow::ClassNode cls | + fieldLike instanceof FieldDefinition + or + fieldLike instanceof AccessorMethodDefinition | - exists(int i | - lbl = Label::parameter(i) and - ref = fn.getParameter(i) + useNodeFlowsToDecorator(base, fieldLike.getADecorator()) and + lbl = Label::decoratedMember() and + cls = fieldLike.getDeclaringClass().flow() and + ( + fieldLike.isStatic() and + ref = cls.getAClassReference().getAPropertyReference(fieldLike.getName()) + or + not fieldLike.isStatic() and + ref = cls.getAnInstanceReference().getAPropertyReference(fieldLike.getName()) ) + ) + } + + /** + * Holds if `ref` is a use of node `nd`. + */ + cached + predicate use(TApiNode nd, DataFlow::Node ref) { + exists(string m, Module mod | nd = MkModuleDef(m) and mod = importableModule(m) | + ref = DataFlow::moduleVarNode(mod) + ) + or + exists(string m, Module mod | nd = MkModuleExport(m) and mod = importableModule(m) | + ref = DataFlow::exportsVarNode(mod) or - lbl = Label::receiver() and - ref = fn.getReceiver() + exists(DataFlow::Node base | use(MkModuleDef(m), base) | + ref = trackUseNode(base).getAPropertyRead("exports") + ) ) or - exists(DataFlow::Node def, DataFlow::ClassNode cls, int i | - rhs(base, def) and cls = trackDefNode(def) - | - lbl = Label::parameter(i) and - ref = cls.getConstructor().getParameter(i) + exists(string m | + nd = MkModuleImport(m) and + ref = DataFlow::moduleImport(m) ) or - exists(string moduleName, string exportName | - base = MkTypeUse(moduleName, exportName) and - lbl = Label::instance() and - ref.(DataFlow::SourceNode).hasUnderlyingType(moduleName, exportName) + exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) | + ref = cls.getAReceiverNode() + or + ref = cls.(DataFlow::ClassNode).getAPrototypeReference() ) or - exists(DataFlow::InvokeNode call | - base = MkSyntheticCallbackArg(call) and - lbl = Label::parameter(1) and - ref = awaited(call) + use(_, _, ref) and + nd = MkUse(ref) + } + + private import semmle.javascript.dataflow.TypeTracking + + /** + * Gets a data-flow node to which `nd`, which is a use of an API-graph node, flows. + * + * The flow from `nd` to that node may be inter-procedural, and is further described by three + * flags: + * + * - `promisified`: if true `true`, the flow goes through a promisification; + * - `boundArgs`: for function values, tracks how many arguments have been bound throughout + * the flow. To ensure termination, we somewhat arbitrarily constrain the number of bound + * arguments to be at most ten. + * - `prop`: if non-empty, the flow is only guaranteed to preserve the value of this property, + * and not necessarily the entire object. + */ + private DataFlow::SourceNode trackUseNode( + DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop, + DataFlow::TypeTracker t + ) { + t.start() and + use(_, nd) and + result = nd and + promisified = false and + boundArgs = 0 and + prop = "" + or + exists(Promisify::PromisifyCall promisify | + trackUseNode(nd, false, boundArgs, prop, t.continue()).flowsTo(promisify.getArgument(0)) and + promisified = true and + prop = "" and + result = promisify ) or - // Handle promisified object member access: promisify(obj).member should be treated as obj.member (promisified) - exists( - Promisify::PromisifyAllCall promisifiedObj, DataFlow::SourceNode originalObj, - string member - | - originalObj.flowsTo(promisifiedObj.getArgument(0)) and - use(base, originalObj) and - lbl = Label::member(member) and - ref = promisifiedObj.getAPropertyRead(member) + exists(DataFlow::PartialInvokeNode pin, DataFlow::Node pred, int predBoundArgs | + trackUseNode(nd, promisified, predBoundArgs, prop, t.continue()).flowsTo(pred) and + prop = "" and + result = pin.getBoundFunction(pred, boundArgs - predBoundArgs) and + boundArgs in [0 .. 10] ) or - decoratorDualEdge(base, lbl, ref) + exists(DataFlow::SourceNode mid | + mid = trackUseNode(nd, promisified, boundArgs, prop, t) and + AdditionalUseStep::step(pragma[only_bind_out](mid), result) + ) or - decoratorUseEdge(base, lbl, ref) + exists(DataFlow::Node pred, string preprop | + trackUseNode(nd, promisified, boundArgs, preprop, t.continue()).flowsTo(pred) and + promisified = false and + boundArgs = 0 and + SharedTypeTrackingStep::loadStoreStep(pred, result, prop) + | + prop = preprop + or + preprop = "" + ) or - // for fields and accessors, mark the reads as use-nodes - decoratorPropEdge(base, lbl, ref.(DataFlow::PropRead)) - ) - } - - /** Holds if `base` is a use-node that flows to the decorator expression of the given decorator. */ - pragma[nomagic] - private predicate useNodeFlowsToDecorator(TApiNode base, Decorator decorator) { - exists(DataFlow::SourceNode decoratorSrc | - use(base, decoratorSrc) and - trackUseNode(decoratorSrc).flowsToExpr(decorator.getExpression()) - ) - } + t = useStep(nd, promisified, boundArgs, prop, result) + } - /** - * Holds if `ref` corresponds to both a use and def-node that should have an incoming edge from `base` labelled `lbl`. - * - * This happens because the decorated value escapes into the decorator function, and is then replaced - * by the function's return value. In the JS analysis we generally assume decorators return their input, - * but library models may want to find the return value. - */ - private predicate decoratorDualEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { - exists(ClassDefinition cls | - useNodeFlowsToDecorator(base, cls.getADecorator()) and - lbl = Label::decoratedClass() and - ref = DataFlow::valueNode(cls) - ) - or - exists(MethodDefinition method | - useNodeFlowsToDecorator(base, method.getADecorator()) and - not method instanceof AccessorMethodDefinition and - lbl = Label::decoratedMember() and - ref = DataFlow::valueNode(method.getBody()) - ) - } + /** + * Holds if `nd`, which is a use of an API-graph node, flows in zero or more potentially + * inter-procedural steps to some intermediate node, and then from that intermediate node to + * `res` in one step. The entire flow is described by the resulting `TypeTracker`. + * + * This predicate exists solely to enforce a better join order in `trackUseNode` above. + */ + pragma[noopt] + private DataFlow::TypeTracker useStep( + DataFlow::Node nd, boolean promisified, int boundArgs, string prop, DataFlow::Node res + ) { + exists(DataFlow::TypeTracker t, StepSummary summary, DataFlow::SourceNode prev | + prev = trackUseNode(nd, promisified, boundArgs, prop, t) and + StepSummary::step(prev, res, summary) and + result = t.append(summary) + ) + } - /** Holds if `ref` is a use that should have an incoming edge from `base` labelled `lbl`, induced by a decorator. */ - private predicate decoratorUseEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { - exists(SetterMethodDefinition accessor | - useNodeFlowsToDecorator(base, - [accessor.getADecorator(), accessor.getCorrespondingGetter().getADecorator()]) and - lbl = Label::decoratedMember() and - ref = DataFlow::parameterNode(accessor.getBody().getParameter(0)) - ) - or - exists(Parameter param | - useNodeFlowsToDecorator(base, param.getADecorator()) and - lbl = Label::decoratedParameter() and - ref = DataFlow::parameterNode(param) - ) - } + private DataFlow::SourceNode trackUseNode( + DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop + ) { + result = trackUseNode(nd, promisified, boundArgs, prop, DataFlow::TypeTracker::end()) + } - /** Holds if `rhs` is a def node that should have an incoming edge from `base` labelled `lbl`, induced by a decorator. */ - private predicate decoratorRhsEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { - exists(GetterMethodDefinition accessor | - useNodeFlowsToDecorator(base, - [accessor.getADecorator(), accessor.getCorrespondingSetter().getADecorator()]) and - lbl = Label::decoratedMember() and - rhs = DataFlow::valueNode(accessor.getBody().getAReturnedExpr()) - ) - } + /** + * Gets a node that is inter-procedurally reachable from `nd`, which is a use of some node. + */ + cached + DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { + result = trackUseNode(nd, false, 0, "") + } - /** - * Holds if `ref` is a reference to a field/accessor that should have en incoming edge from base labelled `lbl`. - * - * Since fields do not have their own data-flow nodes, we generate a node for each read or write. - * For property writes, the right-hand side becomes a def-node and property reads become use-nodes. - * - * For accessors this predicate computes each use of the accessor. - * The return value inside the accessor is computed by the `decoratorRhsEdge` predicate. - */ - private predicate decoratorPropEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::PropRef ref) { - exists(MemberDefinition fieldLike, DataFlow::ClassNode cls | - fieldLike instanceof FieldDefinition + private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) { + t.start() and + rhs(_, nd) and + result = nd.getALocalSource() or - fieldLike instanceof AccessorMethodDefinition - | - useNodeFlowsToDecorator(base, fieldLike.getADecorator()) and - lbl = Label::decoratedMember() and - cls = fieldLike.getDeclaringClass().flow() and - ( - fieldLike.isStatic() and - ref = cls.getAClassReference().getAPropertyReference(fieldLike.getName()) + // additional backwards step from `require('m')` to `exports` or `module.exports` in m + exists(Import imp | imp.getImportedModuleNodeStrict() = trackDefNode(nd, t.continue()) | + result = DataFlow::exportsVarNode(imp.getImportedModule()) or - not fieldLike.isStatic() and - ref = cls.getAnInstanceReference().getAPropertyReference(fieldLike.getName()) + result = DataFlow::moduleVarNode(imp.getImportedModule()).getAPropertyRead("exports") ) - ) - } - - /** - * Holds if `ref` is a use of node `nd`. - */ - cached - predicate use(TApiNode nd, DataFlow::Node ref) { - exists(string m, Module mod | nd = MkModuleDef(m) and mod = importableModule(m) | - ref = DataFlow::moduleVarNode(mod) - ) - or - exists(string m, Module mod | nd = MkModuleExport(m) and mod = importableModule(m) | - ref = DataFlow::exportsVarNode(mod) or - exists(DataFlow::Node base | use(MkModuleDef(m), base) | - ref = trackUseNode(base).getAPropertyRead("exports") + exists(ObjectExpr obj | + obj = trackDefNode(nd, t.continue()).asExpr() and + result = + obj.getAProperty() + .(SpreadProperty) + .getInit() + .(SpreadElement) + .getOperand() + .flow() + .getALocalSource() ) - ) - or - exists(string m | - nd = MkModuleImport(m) and - ref = DataFlow::moduleImport(m) - ) - or - exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) | - ref = cls.getAReceiverNode() or - ref = cls.(DataFlow::ClassNode).getAPrototypeReference() - ) - or - use(_, _, ref) and - nd = MkUse(ref) - } - - private import semmle.javascript.dataflow.TypeTracking - - /** - * Gets a data-flow node to which `nd`, which is a use of an API-graph node, flows. - * - * The flow from `nd` to that node may be inter-procedural, and is further described by three - * flags: - * - * - `promisified`: if true `true`, the flow goes through a promisification; - * - `boundArgs`: for function values, tracks how many arguments have been bound throughout - * the flow. To ensure termination, we somewhat arbitrarily constrain the number of bound - * arguments to be at most ten. - * - `prop`: if non-empty, the flow is only guaranteed to preserve the value of this property, - * and not necessarily the entire object. - */ - private DataFlow::SourceNode trackUseNode( - DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop, - DataFlow::TypeTracker t - ) { - t.start() and - use(_, nd) and - result = nd and - promisified = false and - boundArgs = 0 and - prop = "" - or - exists(Promisify::PromisifyCall promisify | - trackUseNode(nd, false, boundArgs, prop, t.continue()).flowsTo(promisify.getArgument(0)) and - promisified = true and - prop = "" and - result = promisify - ) - or - exists(DataFlow::PartialInvokeNode pin, DataFlow::Node pred, int predBoundArgs | - trackUseNode(nd, promisified, predBoundArgs, prop, t.continue()).flowsTo(pred) and - prop = "" and - result = pin.getBoundFunction(pred, boundArgs - predBoundArgs) and - boundArgs in [0 .. 10] - ) - or - exists(DataFlow::SourceNode mid | - mid = trackUseNode(nd, promisified, boundArgs, prop, t) and - AdditionalUseStep::step(pragma[only_bind_out](mid), result) - ) - or - exists(DataFlow::Node pred, string preprop | - trackUseNode(nd, promisified, boundArgs, preprop, t.continue()).flowsTo(pred) and - promisified = false and - boundArgs = 0 and - SharedTypeTrackingStep::loadStoreStep(pred, result, prop) - | - prop = preprop - or - preprop = "" - ) - or - t = useStep(nd, promisified, boundArgs, prop, result) - } - - /** - * Holds if `nd`, which is a use of an API-graph node, flows in zero or more potentially - * inter-procedural steps to some intermediate node, and then from that intermediate node to - * `res` in one step. The entire flow is described by the resulting `TypeTracker`. - * - * This predicate exists solely to enforce a better join order in `trackUseNode` above. - */ - pragma[noopt] - private DataFlow::TypeTracker useStep( - DataFlow::Node nd, boolean promisified, int boundArgs, string prop, DataFlow::Node res - ) { - exists(DataFlow::TypeTracker t, StepSummary summary, DataFlow::SourceNode prev | - prev = trackUseNode(nd, promisified, boundArgs, prop, t) and - StepSummary::step(prev, res, summary) and - result = t.append(summary) and - // Block argument-passing into 'this' when it determines the call target - not summary = CallReceiverStep() - ) - } + t = defStep(nd, result) + } - private DataFlow::SourceNode trackUseNode( - DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop - ) { - result = trackUseNode(nd, promisified, boundArgs, prop, DataFlow::TypeTracker::end()) - } + /** + * Holds if `nd`, which is a def of an API-graph node, can be reached in zero or more potentially + * inter-procedural steps from some intermediate node, and `prev` flows into that intermediate node + * in one step. The entire flow is described by the resulting `TypeTracker`. + * + * This predicate exists solely to enforce a better join order in `trackDefNode` above. + */ + pragma[noopt] + private DataFlow::TypeBackTracker defStep(DataFlow::Node nd, DataFlow::SourceNode prev) { + exists(DataFlow::TypeBackTracker t, StepSummary summary, DataFlow::Node next | + next = trackDefNode(nd, t) and + StepSummary::step(prev, next, summary) and + result = t.prepend(summary) + ) + } - /** - * Gets a node that is inter-procedurally reachable from `nd`, which is a use of some node. - */ - cached - DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { - result = trackUseNode(nd, false, 0, "") - } + /** + * Gets a node that inter-procedurally flows into `nd`, which is a definition of some node. + */ + cached + DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { + result = trackDefNode(nd, DataFlow::TypeBackTracker::end()) + } - private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) { - t.start() and - rhs(_, nd) and - result = nd.getALocalSource() - or - // additional backwards step from `require('m')` to `exports` or `module.exports` in m - exists(Import imp | imp.getImportedModuleNodeStrict() = trackDefNode(nd, t.continue()) | - result = DataFlow::exportsVarNode(imp.getImportedModule()) + private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) { + t.startInPromise() and + trackUseNode(_, true, _, "").flowsTo(call.getCalleeNode()) and + result = call or - result = DataFlow::moduleVarNode(imp.getImportedModule()).getAPropertyRead("exports") - ) - or - exists(ObjectExpr obj | - obj = trackDefNode(nd, t.continue()).asExpr() and - result = - obj.getAProperty() - .(SpreadProperty) - .getInit() - .(SpreadElement) - .getOperand() - .flow() - .getALocalSource() - ) - or - t = defStep(nd, result) - } - - /** - * Holds if `nd`, which is a def of an API-graph node, can be reached in zero or more potentially - * inter-procedural steps from some intermediate node, and `prev` flows into that intermediate node - * in one step. The entire flow is described by the resulting `TypeTracker`. - * - * This predicate exists solely to enforce a better join order in `trackDefNode` above. - */ - pragma[noopt] - private DataFlow::TypeBackTracker defStep(DataFlow::Node nd, DataFlow::SourceNode prev) { - exists(DataFlow::TypeBackTracker t, StepSummary summary, DataFlow::Node next | - next = trackDefNode(nd, t) and - StepSummary::step(prev, next, summary) and - result = t.prepend(summary) and - // Block argument-passing steps from 'this' back to a receiver when it determines the call target - not summary = CallReceiverStep() - ) - } - - /** - * Gets a node that inter-procedurally flows into `nd`, which is a definition of some node. - */ - cached - DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { - result = trackDefNode(nd, DataFlow::TypeBackTracker::end()) - } - - private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) { - t.startInPromise() and - trackUseNode(_, true, _, "").flowsTo(call.getCalleeNode()) and - result = call - or - exists(DataFlow::TypeTracker t2 | result = awaited(call, t2).track(t2, t)) - } + exists(DataFlow::TypeTracker t2 | result = awaited(call, t2).track(t2, t)) + } - /** - * Gets a node holding the resolved value of promise `call`. - */ - private DataFlow::Node awaited(DataFlow::InvokeNode call) { - result = awaited(call, DataFlow::TypeTracker::end()) - } + /** + * Gets a node holding the resolved value of promise `call`. + */ + private DataFlow::Node awaited(DataFlow::InvokeNode call) { + result = awaited(call, DataFlow::TypeTracker::end()) + } - /** - * Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`. - */ - cached - predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) { - Stages::ApiStage::ref() and - exists(string m | - pred = MkRoot() and - lbl = Label::moduleLabel(m) - | - succ = MkModuleDef(m) + /** + * Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`. + */ + cached + predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) { + Stages::ApiStage::ref() and + exists(string m | + pred = MkRoot() and + lbl = Label::moduleLabel(m) + | + succ = MkModuleDef(m) + or + succ = MkModuleUse(m) + ) or - succ = MkModuleUse(m) - ) - or - exists(string m | - pred = MkModuleDef(m) and - lbl = Label::member("exports") and - succ = MkModuleExport(m) + exists(string m | + pred = MkModuleDef(m) and + lbl = Label::member("exports") and + succ = MkModuleExport(m) + or + pred = MkModuleUse(m) and + lbl = Label::member("exports") and + succ = MkModuleImport(m) + ) or - pred = MkModuleUse(m) and - lbl = Label::member("exports") and - succ = MkModuleImport(m) - ) - or - exists(DataFlow::SourceNode ref | - use(pred, lbl, ref) and - succ = MkUse(ref) - ) - or - exists(DataFlow::Node rhs | rhs(pred, lbl, rhs) | - succ = MkDef(rhs) + exists(DataFlow::SourceNode ref | + use(pred, lbl, ref) and + succ = MkUse(ref) + ) or - exists(DataFlow::ClassNode cls | - cls.getAnInstanceReference().flowsTo(rhs) and - succ = MkClassInstance(cls) + exists(DataFlow::Node rhs | rhs(pred, lbl, rhs) | + succ = MkDef(rhs) + or + exists(DataFlow::ClassNode cls | + cls.getAnInstanceReference().flowsTo(rhs) and + succ = MkClassInstance(cls) + ) ) - ) - or - exists(DataFlow::Node def | - rhs(pred, def) and - lbl = Label::instance() and - succ = MkClassInstance(trackDefNode(def)) - ) - or - exists(string moduleName, string exportName | - pred = MkModuleImport(moduleName) and - lbl = Label::member(exportName) and - succ = MkTypeUse(moduleName, exportName) - ) - or - exists(DataFlow::Node nd, DataFlow::FunctionNode f | - f.getFunction().isAsync() and - pred = MkDef(nd) and - f = trackDefNode(nd) and - lbl = Label::return() and - succ = MkDef(f.getReturnNode()) - ) - or - exists(int bound, DataFlow::InvokeNode call | - lbl = Label::parameter(bound + call.getNumArgument()) and - call = getAPromisifiedInvocation(pred, bound, succ) - ) + or + exists(DataFlow::Node def | + rhs(pred, def) and + lbl = Label::instance() and + succ = MkClassInstance(trackDefNode(def)) + ) + or + exists(string moduleName, string exportName | + pred = MkModuleImport(moduleName) and + lbl = Label::member(exportName) and + succ = MkTypeUse(moduleName, exportName) + ) + or + exists(DataFlow::Node nd, DataFlow::FunctionNode f | + f.getFunction().isAsync() and + pred = MkDef(nd) and + f = trackDefNode(nd) and + lbl = Label::return() and + succ = MkDef(f.getReturnNode()) + ) + or + exists(int bound, DataFlow::InvokeNode call | + lbl = Label::parameter(bound + call.getNumArgument()) and + call = getAPromisifiedInvocation(pred, bound, succ) + ) + } + + /** + * Gets a call to a promisified function represented by `callee` where + * `bound` arguments have been bound. + */ + cached + DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { + exists(DataFlow::SourceNode src | + use(callee, src) and + trackUseNode(src, true, bound, "").flowsTo(result.getCalleeNode()) and + succ = Impl::MkSyntheticCallbackArg(result) + ) + } } + import Stage + /** * Holds if there is an edge from `pred` to `succ` in the API graph. */ @@ -1489,19 +1491,6 @@ module API { /** Gets the shortest distance from the root to `nd` in the API graph. */ cached int distanceFromRoot(TApiNode nd) = shortestDistances(MkRoot/0, edge/2)(_, nd, result) - - /** - * Gets a call to a promisified function represented by `callee` where - * `bound` arguments have been bound. - */ - cached - DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { - exists(DataFlow::SourceNode src | - Impl::use(callee, src) and - trackUseNode(src, true, bound, "").flowsTo(result.getCalleeNode()) and - succ = Impl::MkSyntheticCallbackArg(result) - ) - } } /** From f7208f9a98779647d5b9174d7b89f345a025e156 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 14:07:09 +0200 Subject: [PATCH 27/59] JS: Parameterise the module (still only one instantiation) --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 69 +++++++++++++------ 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 093006d457e2..7f9794bc0758 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -794,8 +794,17 @@ module API { hasSemantics(imp) } + private signature module StageInputSig { + predicate isAdditionalUseRoot(Node node); + + predicate isAdditionalDefRoot(Node node); + + bindingset[node] + predicate inScope(DataFlow::Node node); + } + cached - private module Stage { + private module Stage { /** * Holds if `rhs` is the right-hand side of a definition of a node that should have an * incoming edge from `base` labeled `lbl` in the API graph. @@ -988,9 +997,11 @@ module API { */ cached predicate rhs(TApiNode nd, DataFlow::Node rhs) { + (S::inScope(rhs) or S::isAdditionalDefRoot(nd)) and exists(string m | nd = MkModuleExport(m) | exports(m, rhs)) or rhs(_, _, rhs) and + S::inScope(rhs) and nd = MkDef(rhs) } @@ -1218,30 +1229,37 @@ module API { */ cached predicate use(TApiNode nd, DataFlow::Node ref) { - exists(string m, Module mod | nd = MkModuleDef(m) and mod = importableModule(m) | - ref = DataFlow::moduleVarNode(mod) - ) - or - exists(string m, Module mod | nd = MkModuleExport(m) and mod = importableModule(m) | - ref = DataFlow::exportsVarNode(mod) + (S::inScope(ref) or S::isAdditionalUseRoot(nd)) and + ( + exists(string m, Module mod | nd = MkModuleDef(m) and mod = importableModule(m) | + ref = DataFlow::moduleVarNode(mod) + ) or - exists(DataFlow::Node base | use(MkModuleDef(m), base) | - ref = trackUseNode(base).getAPropertyRead("exports") + exists(string m, Module mod | nd = MkModuleExport(m) and mod = importableModule(m) | + ref = DataFlow::exportsVarNode(mod) + or + exists(DataFlow::Node base | use(MkModuleDef(m), base) | + ref = trackUseNode(base).getAPropertyRead("exports") + ) + ) + or + exists(string m | + nd = MkModuleImport(m) and + ref = DataFlow::moduleImport(m) ) - ) - or - exists(string m | - nd = MkModuleImport(m) and - ref = DataFlow::moduleImport(m) - ) - or - exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) | - ref = cls.getAReceiverNode() or - ref = cls.(DataFlow::ClassNode).getAPrototypeReference() + exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) | + ref = cls.getAReceiverNode() + or + ref = cls.(DataFlow::ClassNode).getAPrototypeReference() + ) ) or use(_, _, ref) and + S::inScope(ref) and + nd = MkUse(ref) + or + S::isAdditionalUseRoot(nd) and nd = MkUse(ref) } @@ -1481,7 +1499,18 @@ module API { } } - import Stage + private module Stage1Input implements StageInputSig { + pragma[inline] + predicate isAdditionalUseRoot(Node node) { none() } + + pragma[inline] + predicate isAdditionalDefRoot(Node node) { none() } + + bindingset[node] + predicate inScope(DataFlow::Node node) { any() } + } + + import Stage /** * Holds if there is an edge from `pred` to `succ` in the API graph. From 0c39e0412226a380be936eaff11f75884872c2e5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 14:07:31 +0200 Subject: [PATCH 28/59] Revert "JS: Remove unused predicate" This reverts commit 336eb37d014dcb9ce765a49f598de5cb14f9a217. --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 7f9794bc0758..d97aa921a2d5 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -778,6 +778,17 @@ module API { } or MkSyntheticCallbackArg(DataFlow::InvokeNode nd) + private predicate needsDefNode(DataFlow::ClassNode cls) { + hasSemantics(cls) and + ( + cls = trackDefNode(_) + or + cls.getAnInstanceReference() = trackDefNode(_) + or + needsDefNode(cls.getADirectSubClass()) + ) + } + class TDef = MkModuleDef or TNonModuleDef; class TNonModuleDef = MkModuleExport or MkClassInstance or MkDef or MkSyntheticCallbackArg; From 46a9b1a46a5833bde8dec600b7a6fd066c64f6c3 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 14:11:46 +0200 Subject: [PATCH 29/59] JS: Fixup restriction of MkClassInstance --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index d97aa921a2d5..f40a76619d8c 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -778,17 +778,6 @@ module API { } or MkSyntheticCallbackArg(DataFlow::InvokeNode nd) - private predicate needsDefNode(DataFlow::ClassNode cls) { - hasSemantics(cls) and - ( - cls = trackDefNode(_) - or - cls.getAnInstanceReference() = trackDefNode(_) - or - needsDefNode(cls.getADirectSubClass()) - ) - } - class TDef = MkModuleDef or TNonModuleDef; class TNonModuleDef = MkModuleExport or MkClassInstance or MkDef or MkSyntheticCallbackArg; @@ -1235,6 +1224,21 @@ module API { ) } + private predicate needsDefNode(DataFlow::ClassNode cls) { + hasSemantics(cls) and + ( + cls = trackDefNode(_) + or + cls.getAnInstanceReference() = trackDefNode(_) + or + needsDefNode(cls.getADirectSubClass()) + or + S::isAdditionalDefRoot(MkClassInstance(cls)) + or + S::isAdditionalUseRoot(MkClassInstance(cls)) // These are also tracked as use-nodes + ) + } + /** * Holds if `ref` is a use of node `nd`. */ @@ -1258,12 +1262,12 @@ module API { nd = MkModuleImport(m) and ref = DataFlow::moduleImport(m) ) + ) + or + exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) and needsDefNode(cls) | + ref = cls.getAReceiverNode() or - exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) | - ref = cls.getAReceiverNode() - or - ref = cls.(DataFlow::ClassNode).getAPrototypeReference() - ) + ref = cls.(DataFlow::ClassNode).getAPrototypeReference() ) or use(_, _, ref) and From 3d638f539daf19418bc80359caa0fcb09bb239c4 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 9 Oct 2025 15:17:36 +0200 Subject: [PATCH 30/59] JS: Moving 'cache' annotations outside the parameterised module --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index f40a76619d8c..d3785e040086 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -803,7 +803,6 @@ module API { predicate inScope(DataFlow::Node node); } - cached private module Stage { /** * Holds if `rhs` is the right-hand side of a definition of a node that should have an @@ -995,7 +994,6 @@ module API { /** * Holds if `rhs` is the right-hand side of a definition of node `nd`. */ - cached predicate rhs(TApiNode nd, DataFlow::Node rhs) { (S::inScope(rhs) or S::isAdditionalDefRoot(nd)) and exists(string m | nd = MkModuleExport(m) | exports(m, rhs)) @@ -1242,7 +1240,6 @@ module API { /** * Holds if `ref` is a use of node `nd`. */ - cached predicate use(TApiNode nd, DataFlow::Node ref) { (S::inScope(ref) or S::isAdditionalUseRoot(nd)) and ( @@ -1364,7 +1361,6 @@ module API { /** * Gets a node that is inter-procedurally reachable from `nd`, which is a use of some node. */ - cached DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { result = trackUseNode(nd, false, 0, "") } @@ -1415,7 +1411,6 @@ module API { /** * Gets a node that inter-procedurally flows into `nd`, which is a definition of some node. */ - cached DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { result = trackDefNode(nd, DataFlow::TypeBackTracker::end()) } @@ -1438,7 +1433,6 @@ module API { /** * Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`. */ - cached predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) { Stages::ApiStage::ref() and exists(string m | @@ -1504,7 +1498,6 @@ module API { * Gets a call to a promisified function represented by `callee` where * `bound` arguments have been bound. */ - cached DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { exists(DataFlow::SourceNode src | use(callee, src) and @@ -1525,7 +1518,36 @@ module API { predicate inScope(DataFlow::Node node) { any() } } - import Stage + private module Stage1 = Stage; + + cached + private module Cached { + cached + predicate rhs(TApiNode nd, DataFlow::Node rhs) { Stage1::rhs(nd, rhs) } + + cached + predicate use(TApiNode nd, DataFlow::Node ref) { Stage1::use(nd, ref) } + + cached + DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { + result = Stage1::trackUseNode(nd) + } + + cached + DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { result = Stage1::trackDefNode(nd) } + + cached + predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) { + Stage1::edge(pred, lbl, succ) + } + + cached + DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { + result = Stage1::getAPromisifiedInvocation(callee, bound, succ) + } + } + + import Cached /** * Holds if there is an edge from `pred` to `succ` in the API graph. From 3db63af57d012a9e9b14178e56755e3a2caa30df Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:01:25 +0200 Subject: [PATCH 31/59] JS: Localize charpred of API::EntryPoint This is needed for localizing ApiLabel later --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 4 ++++ .../ql/lib/semmle/javascript/frameworks/ClientRequests.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/D3.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/Electron.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/History.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/Logging.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/Nest.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/Redux.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/Templating.qll | 2 +- .../ql/lib/semmle/javascript/frameworks/TrustedTypes.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/Vue.qll | 3 +++ .../ql/lib/semmle/javascript/frameworks/WebResponse.qll | 2 ++ javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll | 2 ++ javascript/ql/lib/semmle/javascript/frameworks/Webix.qll | 1 + .../javascript/frameworks/data/internal/ApiGraphModels.qll | 2 ++ .../frameworks/data/internal/ApiGraphModelsSpecific.qll | 2 ++ .../semmle/javascript/security/dataflow/RemoteFlowSources.qll | 2 ++ .../ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql | 1 + 19 files changed, 29 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index d3785e040086..00c483ee53c8 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -676,17 +676,21 @@ module API { * Imports and exports are considered entry points by default, but additional entry points may * be added by extending this class. Typical examples include global variables. */ + overlay[local] abstract class EntryPoint extends string { bindingset[this] EntryPoint() { any() } /** Gets a data-flow node where a value enters the current codebase through this entry-point. */ + overlay[global] DataFlow::SourceNode getASource() { none() } /** Gets a data-flow node where a value leaves the current codebase through this entry-point. */ + overlay[global] DataFlow::Node getASink() { none() } /** Gets an API-node for this entry point. */ + overlay[global] API::Node getANode() { result = root().getASuccessor(Label::entryPoint(this)) } } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll index 22db9f24b99e..9da93400ef92 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll @@ -198,6 +198,7 @@ module ClientRequest { private string urlPropertyName() { result = "url" or result = "uri" } /** An API entry-point for the global variable `axios`. */ + overlay[local?] private class AxiosGlobalEntryPoint extends API::EntryPoint { AxiosGlobalEntryPoint() { this = "axiosGlobal" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll index cc7c07c80c19..138e3b05d576 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll @@ -6,6 +6,7 @@ private import semmle.javascript.security.dataflow.DomBasedXssCustomizations /** Provides classes and predicates modeling aspects of the `d3` library. */ module D3 { /** The global variable `d3` as an entry point for API graphs. */ + overlay[local?] private class D3GlobalEntry extends API::EntryPoint { D3GlobalEntry() { this = "D3GlobalEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll index 796770b96ee0..2d21baac1f98 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll @@ -41,6 +41,7 @@ module Electron { BrowserView() { this = DataFlow::moduleMember("electron", "BrowserView").getAnInstantiation() } } + overlay[local?] private class ElectronEntryPoint extends API::EntryPoint { ElectronEntryPoint() { this = "Electron.Browser" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/History.qll b/javascript/ql/lib/semmle/javascript/frameworks/History.qll index 37c0057f6c1f..224eb2b4b595 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/History.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/History.qll @@ -5,6 +5,7 @@ import javascript /** Provides classes modeling the [`history`](https://npmjs.org/package/history) library. */ module History { /** The global variable `HistoryLibrary` as an entry point for API graphs. */ + overlay[local?] private class HistoryGlobalEntry extends API::EntryPoint { HistoryGlobalEntry() { this = "HistoryLibrary" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll index 1adaed5b4398..9a94fc26341c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll @@ -13,6 +13,7 @@ private module Immutable { /** * An API entrypoint for the global `Immutable` variable. */ + overlay[local?] private class ImmutableGlobalEntry extends API::EntryPoint { ImmutableGlobalEntry() { this = "ImmutableGlobalEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll index aa0151595dfd..e297dbd7afde 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll @@ -32,6 +32,7 @@ private module Console { /** * An API entrypoint for the global `console` variable. */ + overlay[local?] private class ConsoleGlobalEntry extends API::EntryPoint { ConsoleGlobalEntry() { this = "ConsoleGlobalEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll index d7474aae8ca4..4c32f70b9816 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll @@ -140,6 +140,7 @@ module NestJS { } /** API node entry point for custom implementations of `ValidationPipe` (a common pattern). */ + overlay[local?] private class ValidationNodeEntry extends API::EntryPoint { ValidationNodeEntry() { this = "ValidationNodeEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll index 78931da585a4..3aaf07f637d9 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll @@ -1099,6 +1099,7 @@ module Redux { * Used to catch cases where the `connect` function was not recognized by API graphs (usually because of it being * wrapped in another function, which API graphs won't look through). */ + overlay[local?] private class HeuristicConnectEntryPoint extends API::EntryPoint { HeuristicConnectEntryPoint() { this = "react-redux-connect" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll index f1f91785329c..8932c2753ab2 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll @@ -703,7 +703,7 @@ module Templating { * * These API nodes are used in the `getTemplateInput` predicate. */ - overlay[global] + overlay[local?] private class IncludeFunctionAsEntryPoint extends API::EntryPoint { IncludeFunctionAsEntryPoint() { this = "IncludeFunctionAsEntryPoint" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll index ca9de4e481fa..8d32c976c57d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll @@ -11,6 +11,7 @@ private import semmle.javascript.security.dataflow.CodeInjectionCustomizations * Module for working with uses of the [Trusted Types API](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API). */ module TrustedTypes { + overlay[local?] private class TrustedTypesEntry extends API::EntryPoint { TrustedTypesEntry() { this = "TrustedTypesEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll index f571648294c2..1052e91d4c13 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll @@ -7,6 +7,7 @@ import semmle.javascript.ViewComponentInput module Vue { /** The global variable `Vue`, as an API graph entry point. */ + overlay[local?] private class GlobalVueEntryPoint extends API::EntryPoint { GlobalVueEntryPoint() { this = "VueEntryPoint" } @@ -18,6 +19,7 @@ module Vue { * * This `EntryPoint` is used by `SingleFileComponent::getOwnOptions()`. */ + overlay[local?] private class VueExportEntryPoint extends API::EntryPoint { VueExportEntryPoint() { this = "VueExportEntryPoint" } @@ -437,6 +439,7 @@ module Vue { * * This entry point is used in `SingleFileComponent::getComponentRef()`. */ + overlay[local?] private class VueFileImportEntryPoint extends API::EntryPoint { VueFileImportEntryPoint() { this = "VueFileImportEntryPoint" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll b/javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll index dfdee73c9d90..9c24f84ecbc8 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll @@ -5,6 +5,7 @@ private import javascript /** Treats `Response` as an entry point for API graphs. */ +overlay[local?] private class ResponseEntryPoint extends API::EntryPoint { ResponseEntryPoint() { this = "global.Response" } @@ -12,6 +13,7 @@ private class ResponseEntryPoint extends API::EntryPoint { } /** Treats `Headers` as an entry point for API graphs. */ +overlay[local?] private class HeadersEntryPoint extends API::EntryPoint { HeadersEntryPoint() { this = "global.Headers" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll b/javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll index f71b1cf9e0d6..2ec1b784f19f 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll @@ -48,6 +48,7 @@ private predicate areLibrariesCompatible( } /** Treats `WebSocket` as an entry point for API graphs. */ +overlay[local?] private class WebSocketEntryPoint extends API::EntryPoint { WebSocketEntryPoint() { this = "global.WebSocket" } @@ -55,6 +56,7 @@ private class WebSocketEntryPoint extends API::EntryPoint { } /** Treats `SockJS` as an entry point for API graphs. */ +overlay[local?] private class SockJSEntryPoint extends API::EntryPoint { SockJSEntryPoint() { this = "global.SockJS" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll b/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll index effd49c632bf..3ce4e78ba3a3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll @@ -9,6 +9,7 @@ private import javascript */ module Webix { /** The global variable `webix` as an entry point for API graphs. */ + overlay[local?] private class WebixGlobalEntry extends API::EntryPoint { WebixGlobalEntry() { this = "WebixGlobalEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll index 80ec45a3cf17..68f2210bff28 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll @@ -492,6 +492,7 @@ private predicate invocationMatchesCallSiteFilter( Specific::invocationMatchesExtraCallSiteFilter(invoke, token) } +overlay[local?] private class TypeModelUseEntry extends API::EntryPoint { private string type; @@ -505,6 +506,7 @@ private class TypeModelUseEntry extends API::EntryPoint { API::Node getNodeForType(string type_) { type = type_ and result = this.getANode() } } +overlay[local?] private class TypeModelDefEntry extends API::EntryPoint { private string type; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll index 2074b18600dc..7904a2b76c6c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -93,6 +93,7 @@ private predicate parseRelevantTypeString(string rawType, string package, string } /** Holds if `global` is a global variable referenced via a the `global` package in a CSV row. */ +overlay[local] private predicate isRelevantGlobal(string global) { exists(AccessPath path, AccessPathToken token | isRelevantFullPath("global", path) and @@ -103,6 +104,7 @@ private predicate isRelevantGlobal(string global) { } /** An API graph entry point for global variables mentioned in a model. */ +overlay[local?] private class GlobalApiEntryPoint extends API::EntryPoint { string global; diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll index 58600c579a84..9f4975e605ae 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll @@ -114,6 +114,7 @@ class ClientSideRemoteFlowKind extends string { * `name` and `address` of global variable `user` should be considered as remote flow sources with * source type "user input". */ +overlay[local?] private class RemoteFlowSourceAccessPath extends JsonString { string sourceType; @@ -167,6 +168,7 @@ private class RemoteFlowSourceAccessPath extends JsonString { * The global variable referenced by a `RemoteFlowSourceAccessPath`, declared as an API * entry point. */ +overlay[local?] private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint { string name; diff --git a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql index 3502c0ea5561..89ab2f3f9449 100644 --- a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql +++ b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql @@ -1,3 +1,4 @@ +overlay[local?] class CustomEntryPoint extends API::EntryPoint { CustomEntryPoint() { this = "CustomEntryPoint" } From 6018df3c70bead7df5a42f94d4b8539b92543f69 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:02:35 +0200 Subject: [PATCH 32/59] JS: Localize MkModuleExport --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 00c483ee53c8..9440d49be3a8 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -740,20 +740,9 @@ module API { MkRoot() or MkModuleDef(string m) { exists(MkModuleExport(m)) } or MkModuleUse(string m) { exists(MkModuleImport(m)) } or - MkModuleExport(string m) { - exists(Module mod | mod = importableModule(m) | - // exclude modules that don't actually export anything - exports(m, _) - or - exports(m, _, _) - or - exists(NodeModule nm | nm = mod | - exists(Ssa::implicitInit([nm.getModuleVariable(), nm.getExportsVariable()])) - ) - ) - } or MkModuleImport(string m) { imports(_, m) + MkModuleExport(string m) { isDeclaredPackageName(m) } or or any(TypeAnnotation n).hasUnderlyingType(m, _) } or @@ -1949,3 +1938,8 @@ private Module importableModule(string m) { m = pkg.getPackageName() ) } + +overlay[local] +private predicate isDeclaredPackageName(string m) { + m = any(PackageJson pkg).getDeclaredPackageName() +} From 523054b93b68071383d2e02da49c5ac98605013c Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:03:03 +0200 Subject: [PATCH 33/59] JS: Localize MkModuleImport --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 9440d49be3a8..594966cbbbf2 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -740,9 +740,8 @@ module API { MkRoot() or MkModuleDef(string m) { exists(MkModuleExport(m)) } or MkModuleUse(string m) { exists(MkModuleImport(m)) } or - MkModuleImport(string m) { - imports(_, m) MkModuleExport(string m) { isDeclaredPackageName(m) } or + MkModuleImport(string m) { isImportedPackageName(m) } or or any(TypeAnnotation n).hasUnderlyingType(m, _) } or @@ -1943,3 +1942,9 @@ overlay[local] private predicate isDeclaredPackageName(string m) { m = any(PackageJson pkg).getDeclaredPackageName() } + +overlay[local] +private predicate isImportedPackageName(string m) { + m = any(Import imprt).getImportedPathString() and + m.regexpMatch("[^./].*") +} From 5d09ab5c73b7f0c68ed0f74e21fb7bcca73cda24 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:03:21 +0200 Subject: [PATCH 34/59] JS: Localize MkClassInstance --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 594966cbbbf2..97dbb2d89a25 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -742,10 +742,11 @@ module API { MkModuleUse(string m) { exists(MkModuleImport(m)) } or MkModuleExport(string m) { isDeclaredPackageName(m) } or MkModuleImport(string m) { isImportedPackageName(m) } or + MkClassInstance(DataFlow::SourceNode cls) { + cls = any(Function f).flow() or - any(TypeAnnotation n).hasUnderlyingType(m, _) + cls = any(ClassDefinition c).flow() } or - MkClassInstance(DataFlow::ClassNode cls) or MkDef(DataFlow::Node nd) { nd = any(DataFlow::PropWrite w).getRhs() or From 77da92f60444dcf519b976bcea3cf6f8ca5a3068 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:04:28 +0200 Subject: [PATCH 35/59] JS: Further localize MkDef --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 97dbb2d89a25..0582504900ce 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -754,15 +754,13 @@ module API { or nd = any(DataFlow::FunctionNode fn).getAReturn() or - nd = any(Module m).getAnExportedValue(_) - or - nd = any(Module m).getABulkExportedNode() - or nd = any(DataFlow::InvokeNode i).getAnArgument() or nd = any(DataFlow::InvokeNode i).getASpreadArgument() or - nd = any(EntryPoint e).getASink() + nd = DataFlow::valueNode(any(ExportNamedDeclaration decl).getOperand()) + or + nd = DataFlow::valueNode(any(ExportDefaultDeclaration decl).getOperand()) } or MkUse(DataFlow::Node nd) { nd instanceof DataFlow::SourceNode } or /** A use of a TypeScript type. */ From aa7a02ef0d0ee8c4ffbdef6f4893e4aa211adf18 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:04:44 +0200 Subject: [PATCH 36/59] JS: Temporarily disable MkTypeUse (too hard to localize for now) --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 0582504900ce..47c25ab0f312 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -765,7 +765,8 @@ module API { MkUse(DataFlow::Node nd) { nd instanceof DataFlow::SourceNode } or /** A use of a TypeScript type. */ MkTypeUse(string moduleName, string exportName) { - any(TypeAnnotation n).hasUnderlyingType(moduleName, exportName) + // any(TypeAnnotation n).hasUnderlyingType(moduleName, exportName) + none() // TODO } or MkSyntheticCallbackArg(DataFlow::InvokeNode nd) From 93aa1906284b234e1e95372f9612b1af128df688 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:05:08 +0200 Subject: [PATCH 37/59] JS: Remove unused predicate --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 8 -------- 1 file changed, 8 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 47c25ab0f312..6ece814495a5 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -778,14 +778,6 @@ module API { private predicate hasSemantics(DataFlow::Node nd) { not nd.getTopLevel().isExterns() } - /** Holds if `imp` is an import of module `m`. */ - private predicate imports(DataFlow::Node imp, string m) { - imp = DataFlow::moduleImport(m) and - // path must not start with a dot or a slash - m.regexpMatch("[^./].*") and - hasSemantics(imp) - } - private signature module StageInputSig { predicate isAdditionalUseRoot(Node node); From 8fcaa72c5e2eb1772c787fe03c8beea45e0212da Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:15:10 +0200 Subject: [PATCH 38/59] JS: Make API nodes and labels local --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 6ece814495a5..a4392d2159cb 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -735,6 +735,7 @@ module API { */ cached private module Impl { + overlay[local] cached newtype TApiNode = MkRoot() or @@ -1600,6 +1601,7 @@ module API { class NewNode extends InvokeNode, DataFlow::NewNode { } /** Provides classes modeling the various edges (labels) in the API graph. */ + overlay[local] module Label { /** A label in the API-graph */ class ApiLabel extends TLabel { @@ -1638,6 +1640,7 @@ module API { * This is to support code patterns where the property name is actually constant, * but the property name has been factored into a library. */ + overlay[global] private string getAnIndirectPropName(DataFlow::PropRef ref) { exists(DataFlow::Node pred | FlowSteps::propertyFlowStep(pred, ref.getPropertyNameExpr().flow()) and @@ -1648,16 +1651,19 @@ module API { /** * Gets unique result of `getAnIndirectPropName` if there is one. */ + overlay[global] private string getIndirectPropName(DataFlow::PropRef ref) { result = unique(string s | s = getAnIndirectPropName(ref)) } + overlay[global] pragma[nomagic] private predicate isEnumeratedPropName(DataFlow::Node node) { node.getAPredecessor*() instanceof EnumeratedPropName } /** Gets the `member` edge label for the given property reference. */ + overlay[global] ApiLabel memberFromRef(DataFlow::PropRef pr) { exists(string pn | pn = pr.getPropertyName() or pn = getIndirectPropName(pr) | result = member(pn) and @@ -1724,9 +1730,17 @@ module API { MkLabelInstance() or MkLabelContent(DataFlow::Content content) or MkLabelMember(string name) { - name instanceof PropertyName + name instanceof ContentPrivate::PropertyName + or + name = any(DataFlow::PropRef pr).getPropertyName() + or + AccessPath::isAssignedInUniqueFile(name) + or + exists(AccessPath::getAnAssignmentTo(_, name)) + or + name = DataFlow::PseudoProperties::arrayLikeElement() or - exists(Impl::MkTypeUse(_, name)) + name = any(TypeAccess t).getIdentifier().getName() } or MkLabelParameter(int i) { i = From 6c20d52658f20c232a0769cc7ee354925cdfa105 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:15:27 +0200 Subject: [PATCH 39/59] JS: Apply forceLocal overlay trick to API graphs --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 106 +++++++++++++++++- 1 file changed, 101 insertions(+), 5 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index a4392d2159cb..d99abe616891 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1350,6 +1350,13 @@ module API { result = trackUseNode(nd, false, 0, "") } + /** + * Gets a node whose forward tracking reaches `nd` in some state (e.g. possibly inside a content at this point). + */ + DataFlow::SourceNode trackUseNodeAnyState(DataFlow::SourceNode nd) { + result = trackUseNode(nd, _, _, _, _) + } + private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) { t.start() and rhs(_, nd) and @@ -1400,6 +1407,11 @@ module API { result = trackDefNode(nd, DataFlow::TypeBackTracker::end()) } + /** + * Gets a node reached by the backwards tracking of `nd` in some state (e.g. possibly inside a content at this point). + */ + DataFlow::SourceNode trackDefNodeAnyState(DataFlow::Node nd) { result = trackDefNode(nd, _) } + private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) { t.startInPromise() and trackUseNode(_, true, _, "").flowsTo(call.getCalleeNode()) and @@ -1505,25 +1517,109 @@ module API { private module Stage1 = Stage; + overlay[local] + private module Stage1Local { + predicate use(TApiNode node, DataFlow::Node ref) = forceLocal(Stage1::use/2)(node, ref) + + predicate rhs(TApiNode node, DataFlow::Node def) = forceLocal(Stage1::rhs/2)(node, def) + + DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) = + forceLocal(Stage1::trackUseNode/1)(nd, result) + + DataFlow::SourceNode trackUseNodeAnyState(DataFlow::SourceNode nd) = + forceLocal(Stage1::trackUseNodeAnyState/1)(nd, result) + + DataFlow::SourceNode trackDefNode(DataFlow::SourceNode nd) = + forceLocal(Stage1::trackDefNode/1)(nd, result) + + DataFlow::SourceNode trackDefNodeAnyState(DataFlow::Node nd) = + forceLocal(Stage1::trackDefNodeAnyState/1)(nd, result) + + predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) = + forceLocal(Stage1::edge/3)(pred, lbl, succ) + } + + private module Stage2Input implements StageInputSig { + bindingset[node] + overlay[global] + pragma[inline_late] + private predicate isInOverlayChangedFile(DataFlow::Node node) { + overlayChangedFiles(node.getFile().getAbsolutePath()) + } + + pragma[nomagic] + private predicate shouldTrackIntoOverlay(DataFlow::SourceNode nd) { + exists(DataFlow::Node overlayNode | + StepSummary::step(Stage1Local::trackUseNodeAnyState(nd), overlayNode, _) and + isInOverlayChangedFile(overlayNode) + ) + } + + pragma[nomagic] + predicate isAdditionalUseRoot(Node node) { + exists(DataFlow::Node ref | + shouldTrackIntoOverlay(ref) and + Stage1Local::use(node, ref) + ) + } + + pragma[nomagic] + private predicate shouldBacktrackIntoOverlay(DataFlow::SourceNode nd) { + exists(DataFlow::Node overlayNode | + StepSummary::step(overlayNode, Stage1Local::trackDefNodeAnyState(nd), _) and + isInOverlayChangedFile(overlayNode) + ) + } + + pragma[nomagic] + predicate isAdditionalDefRoot(Node node) { + exists(DataFlow::Node def | + shouldBacktrackIntoOverlay(def) and + Stage1Local::rhs(node, def) + ) + } + + bindingset[node] + predicate inScope(DataFlow::Node node) { isInOverlayChangedFile(node) } + } + + private module Stage2 = Stage; + cached private module Cached { cached - predicate rhs(TApiNode nd, DataFlow::Node rhs) { Stage1::rhs(nd, rhs) } + predicate rhs(TApiNode nd, DataFlow::Node rhs) { + Stage1Local::rhs(nd, rhs) + or + Stage2::rhs(nd, rhs) + } cached - predicate use(TApiNode nd, DataFlow::Node ref) { Stage1::use(nd, ref) } + predicate use(TApiNode nd, DataFlow::Node ref) { + Stage1Local::use(nd, ref) + or + Stage2::use(nd, ref) + } cached DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { - result = Stage1::trackUseNode(nd) + result = Stage1Local::trackUseNode(nd) + or + result = Stage2::trackUseNode(nd) } cached - DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { result = Stage1::trackDefNode(nd) } + DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { + result = Stage1Local::trackDefNode(nd) + or + result = Stage2::trackDefNode(nd) + } cached predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) { - Stage1::edge(pred, lbl, succ) + Stage1Local::edge(pred, lbl, succ) + or + Stage2::edge(pred, lbl, succ) } cached From e9fe48b6501b1cea9989fd33b69c86a716050608 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:41:44 +0200 Subject: [PATCH 40/59] JS: Also forceLocal getAPromisifiedInvocation --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index d99abe616891..9bd5e7ee55fc 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1537,6 +1537,9 @@ module API { predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) = forceLocal(Stage1::edge/3)(pred, lbl, succ) + + DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) = + forceLocal(Stage1::getAPromisifiedInvocation/3)(callee, bound, succ, result) } private module Stage2Input implements StageInputSig { @@ -1624,7 +1627,9 @@ module API { cached DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { - result = Stage1::getAPromisifiedInvocation(callee, bound, succ) + result = Stage1Local::getAPromisifiedInvocation(callee, bound, succ) + or + result = Stage2::getAPromisifiedInvocation(callee, bound, succ) } } From 8489bdd66e9990ccf8ddfc83280686c82b5b92d4 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:42:01 +0200 Subject: [PATCH 41/59] JS: Stop dependeding on getPath() for toString() --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 9bd5e7ee55fc..e6e96129c45c 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -613,12 +613,12 @@ module API { /** A node corresponding to a definition of an API component. */ class Definition extends Node, Impl::TDef { - override string toString() { result = "def " + this.getPath() } + override string toString() { result = "def " + this.getInducingNode().toString() } } /** A node corresponding to the use of an API component. */ class Use extends Node, Impl::TUse { - override string toString() { result = "use " + this.getPath() } + override string toString() { result = "use " + this.getInducingNode().toString() } } /** Gets the root node. */ From 60c6c0eaea2b930dd402331a3051106057891402 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:42:12 +0200 Subject: [PATCH 42/59] JS:Add more member labels --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index e6e96129c45c..c46a07320cda 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1842,6 +1842,8 @@ module API { name = DataFlow::PseudoProperties::arrayLikeElement() or name = any(TypeAccess t).getIdentifier().getName() + or + name = any(Expr s).getStringValue() } or MkLabelParameter(int i) { i = From 20b2ac0657552df63f32aeb04a1b4d7a664a8955 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:42:22 +0200 Subject: [PATCH 43/59] JS: Add predicate for detecting lost edges --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index c46a07320cda..320377d15724 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1635,6 +1635,13 @@ module API { import Cached + private module Debug { + query predicate lostEdge(Node pred, Label::ApiLabel lbl, Node succ) { + Stage1::edge(pred, lbl, succ) and + not Cached::edge(pred, lbl, succ) + } + } + /** * Holds if there is an edge from `pred` to `succ` in the API graph. */ From e88ed6989fc4ca3b9564ddedbfba3e7c841f77bc Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:51:47 +0200 Subject: [PATCH 44/59] JS: Add MkDef case for 'export const bar = foo' --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 320377d15724..11a27c39a4f1 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -762,6 +762,8 @@ module API { nd = DataFlow::valueNode(any(ExportNamedDeclaration decl).getOperand()) or nd = DataFlow::valueNode(any(ExportDefaultDeclaration decl).getOperand()) + or + nd = any(ExportNamedDeclaration decl).getOperand().(DeclStmt).getADecl().getInit().flow() } or MkUse(DataFlow::Node nd) { nd instanceof DataFlow::SourceNode } or /** A use of a TypeScript type. */ From f1177acf0c904c4697491c5aceb264258a034de6 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:58:31 +0200 Subject: [PATCH 45/59] Debug predicates for missing def/use nodes --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 11a27c39a4f1..992b6ca74635 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -795,7 +795,7 @@ module API { * Holds if `rhs` is the right-hand side of a definition of a node that should have an * incoming edge from `base` labeled `lbl` in the API graph. */ - private predicate rhs(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { + predicate rhs(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { hasSemantics(rhs) and ( base = MkRoot() and @@ -1031,7 +1031,7 @@ module API { * Holds if `ref` is a use of a node that should have an incoming edge from `base` labeled * `lbl` in the API graph. */ - private predicate use(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { + predicate use(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { hasSemantics(ref) and ( base = MkRoot() and @@ -1638,6 +1638,16 @@ module API { import Cached private module Debug { + query predicate missingDefNode(DataFlow::Node node) { + Stage1::rhs(_, _, node) and + not exists(MkDef(node)) + } + + query predicate missingUseNode(DataFlow::Node node) { + Stage1::use(_, _, node) and + not exists(MkUse(node)) + } + query predicate lostEdge(Node pred, Label::ApiLabel lbl, Node succ) { Stage1::edge(pred, lbl, succ) and not Cached::edge(pred, lbl, succ) From c900bafacc4597bb2b6000f3d9eaf16dd80b2b8d Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 10:58:50 +0200 Subject: [PATCH 46/59] JS: Add MkDef case for export namespace specifiers --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 992b6ca74635..e07b237e8ba5 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -764,6 +764,8 @@ module API { nd = DataFlow::valueNode(any(ExportDefaultDeclaration decl).getOperand()) or nd = any(ExportNamedDeclaration decl).getOperand().(DeclStmt).getADecl().getInit().flow() + or + nd = any(ExportNamespaceSpecifier spec | exists(spec.getExportedName())).flow() } or MkUse(DataFlow::Node nd) { nd instanceof DataFlow::SourceNode } or /** A use of a TypeScript type. */ From 3b776e75abe797016069315f405302719f95c92c Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 11:17:53 +0200 Subject: [PATCH 47/59] JS: Restrict entry point edges to those in scope --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index e07b237e8ba5..ed92441f5f07 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1039,7 +1039,8 @@ module API { base = MkRoot() and exists(EntryPoint e | lbl = Label::entryPoint(e) and - ref = e.getASource() + ref = e.getASource() and + S::inScope(ref) ) or // property reads From 981cf139d0de2c44ad0eb7d6a5ee60e3e46ebc11 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 11:18:27 +0200 Subject: [PATCH 48/59] JS: Change signature of 'edges' to support quick eval --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index ed92441f5f07..e145e381a4e0 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1624,7 +1624,7 @@ module API { } cached - predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) { + predicate edge(Node pred, Label::ApiLabel lbl, Node succ) { Stage1Local::edge(pred, lbl, succ) or Stage2::edge(pred, lbl, succ) From f90f8630b9c28f560b60bae401d11fbd7752e7d6 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 6 Oct 2025 11:39:54 +0200 Subject: [PATCH 49/59] JS: Refine criteria so that explicit this-passing is not affected --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index e145e381a4e0..8c750e66314f 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1338,7 +1338,9 @@ module API { exists(DataFlow::TypeTracker t, StepSummary summary, DataFlow::SourceNode prev | prev = trackUseNode(nd, promisified, boundArgs, prop, t) and StepSummary::step(prev, res, summary) and - result = t.append(summary) + result = t.append(summary) and + // Block argument-passing into 'this' when it determines the call target + not summary = CallReceiverStep() ) } From a58b1b436aa0d42ff564a52342ed604e15076c1e Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 11:42:27 +0200 Subject: [PATCH 50/59] JS: Add receivers to MkDef --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 8c750e66314f..e9daded41b05 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -759,6 +759,8 @@ module API { or nd = any(DataFlow::InvokeNode i).getASpreadArgument() or + nd = any(DataFlow::CallNode c).getReceiver() + or nd = DataFlow::valueNode(any(ExportNamedDeclaration decl).getOperand()) or nd = DataFlow::valueNode(any(ExportDefaultDeclaration decl).getOperand()) From a1c41cc30c2d6b8b86b5efdd4bfcbf8f9a1da508 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 11:42:41 +0200 Subject: [PATCH 51/59] JS: Minor improvements to some join orders --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index e9daded41b05..54cb6689deaa 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -785,6 +785,10 @@ module API { private predicate hasSemantics(DataFlow::Node nd) { not nd.getTopLevel().isExterns() } + bindingset[nd] + pragma[inline_late] + private predicate hasSemanticsLate(DataFlow::Node nd) { hasSemantics(nd) } + private signature module StageInputSig { predicate isAdditionalUseRoot(Node node); @@ -1264,9 +1268,13 @@ module API { nd = MkUse(ref) or S::isAdditionalUseRoot(nd) and - nd = MkUse(ref) + nd = mkUseLate(ref) } + bindingset[node] + pragma[inline_late] + private TApiNode mkUseLate(DataFlow::Node node) { result = MkUse(node) } + private import semmle.javascript.dataflow.TypeTracking /** @@ -1552,18 +1560,31 @@ module API { } private module Stage2Input implements StageInputSig { - bindingset[node] overlay[global] - pragma[inline_late] + pragma[nomagic] private predicate isInOverlayChangedFile(DataFlow::Node node) { overlayChangedFiles(node.getFile().getAbsolutePath()) } + bindingset[node] + overlay[global] + pragma[inline_late] + private predicate isInOverlayChangedFileLate(DataFlow::Node node) { + isInOverlayChangedFile(node) + } + + pragma[nomagic] + private predicate stepIntoOverlay(DataFlow::Node node1, DataFlow::Node node2) { + StepSummary::step(node1, node2, _) and + isInOverlayChangedFile(node2) and + not isInOverlayChangedFileLate(node1) and + hasSemanticsLate(node1) + } + pragma[nomagic] private predicate shouldTrackIntoOverlay(DataFlow::SourceNode nd) { exists(DataFlow::Node overlayNode | - StepSummary::step(Stage1Local::trackUseNodeAnyState(nd), overlayNode, _) and - isInOverlayChangedFile(overlayNode) + stepIntoOverlay(Stage1Local::trackUseNodeAnyState(nd), overlayNode) ) } @@ -1575,11 +1596,18 @@ module API { ) } + pragma[nomagic] + private predicate stepOutOfOverlay(DataFlow::Node node1, DataFlow::Node node2) { + StepSummary::step(node1, node2, _) and + isInOverlayChangedFile(node1) and + not isInOverlayChangedFileLate(node2) and + hasSemanticsLate(node2) + } + pragma[nomagic] private predicate shouldBacktrackIntoOverlay(DataFlow::SourceNode nd) { exists(DataFlow::Node overlayNode | - StepSummary::step(overlayNode, Stage1Local::trackDefNodeAnyState(nd), _) and - isInOverlayChangedFile(overlayNode) + stepOutOfOverlay(overlayNode, Stage1Local::trackDefNodeAnyState(nd)) ) } From b7cd35ffc70fbf5659ce7640a377954418f0b5d8 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 13:12:30 +0200 Subject: [PATCH 52/59] wip --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 54cb6689deaa..6fc9cd561463 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1528,8 +1528,11 @@ module API { pragma[inline] predicate isAdditionalDefRoot(Node node) { none() } + overlay[local] + private predicate isOverlay() { databaseMetadata("isOverlay", "true") } + bindingset[node] - predicate inScope(DataFlow::Node node) { any() } + predicate inScope(DataFlow::Node node) { not isOverlay() and exists(node) } } private module Stage1 = Stage; From 67eef3a0931012a7bd01a866faa4357d0c3e7830 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 13:33:40 +0200 Subject: [PATCH 53/59] JS: Add back CallReceiverStep() restriction This was initially lost after rebasing with indentation changes --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 6fc9cd561463..729178e92774 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1413,7 +1413,9 @@ module API { exists(DataFlow::TypeBackTracker t, StepSummary summary, DataFlow::Node next | next = trackDefNode(nd, t) and StepSummary::step(prev, next, summary) and - result = t.prepend(summary) + result = t.prepend(summary) and + // Block argument-passing into 'this' when it determines the call target + not summary = CallReceiverStep() ) } From 05e2d268ec41cac46541ee4264fb93d65b0df8d8 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 14:22:56 +0200 Subject: [PATCH 54/59] JS: Update debugging stuff in API graphs --- .../ql/lib/semmle/javascript/ApiGraphs.qll | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 729178e92774..a0927f850cb7 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1678,20 +1678,40 @@ module API { import Cached private module Debug { + private module FullInput implements StageInputSig { + pragma[inline] + predicate isAdditionalUseRoot(Node node) { none() } + + pragma[inline] + predicate isAdditionalDefRoot(Node node) { none() } + + bindingset[node] + predicate inScope(DataFlow::Node node) { any() } + } + + private module Full = Stage; + query predicate missingDefNode(DataFlow::Node node) { - Stage1::rhs(_, _, node) and + Full::rhs(_, _, node) and not exists(MkDef(node)) } query predicate missingUseNode(DataFlow::Node node) { - Stage1::use(_, _, node) and + Full::use(_, _, node) and not exists(MkUse(node)) } query predicate lostEdge(Node pred, Label::ApiLabel lbl, Node succ) { - Stage1::edge(pred, lbl, succ) and + Full::edge(pred, lbl, succ) and not Cached::edge(pred, lbl, succ) } + + query predicate counts(int numEdges, int numOverlayEdges, float ratio) { + numEdges = count(Node pred, Label::ApiLabel lbl, Node succ | Full::edge(pred, lbl, succ)) and + numOverlayEdges = + count(Node pred, Label::ApiLabel lbl, Node succ | Stage2::edge(pred, lbl, succ)) and + ratio = numOverlayEdges / numEdges.(float) + } } /** From dc4ca96b4e6d70a5dd12233cc9d46193ccede78c Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 14:23:17 +0200 Subject: [PATCH 55/59] JS: Mass overlay[local?] --- javascript/ql/lib/Customizations.qll | 2 ++ .../ql/lib/Declarations/Declarations.qll | 2 ++ .../ql/lib/Declarations/UnusedVariable.qll | 2 ++ .../ql/lib/Expressions/DOMProperties.qll | 2 ++ javascript/ql/lib/IDEContextual.qll | 2 ++ .../LanguageFeatures/UnusedIndexVariable.qll | 2 +- javascript/ql/lib/default.qll | 2 ++ javascript/ql/lib/definitions.qll | 2 ++ .../ql/lib/external/ExternalArtifact.qll | 2 ++ javascript/ql/lib/javascript.qll | 2 ++ javascript/ql/lib/semmle/files/FileSystem.qll | 2 ++ .../ql/lib/semmle/javascript/Actions.qll | 2 ++ .../ql/lib/semmle/javascript/Aliases.qll | 2 ++ .../ql/lib/semmle/javascript/Arrays.qll | 3 +++ .../ql/lib/semmle/javascript/Base64.qll | 2 ++ .../ql/lib/semmle/javascript/BasicBlocks.qll | 2 ++ .../lib/semmle/javascript/CanonicalNames.qll | 1 + .../semmle/javascript/CharacterEscapes.qll | 2 ++ .../ql/lib/semmle/javascript/Collections.qll | 2 ++ .../ql/lib/semmle/javascript/Concepts.qll | 2 ++ javascript/ql/lib/semmle/javascript/DOM.qll | 2 ++ .../javascript/DefensiveProgramming.qll | 2 ++ .../javascript/DynamicPropertyAccess.qll | 2 ++ .../ql/lib/semmle/javascript/EmailClients.qll | 3 +++ .../lib/semmle/javascript/GeneratedCode.qll | 2 ++ .../ql/lib/semmle/javascript/Generators.qll | 2 ++ .../lib/semmle/javascript/HtmlSanitizers.qll | 2 ++ .../lib/semmle/javascript/InclusionTests.qll | 2 ++ .../ql/lib/semmle/javascript/JsonParsers.qll | 2 ++ .../ql/lib/semmle/javascript/JsonSchema.qll | 2 ++ .../semmle/javascript/JsonStringifiers.qll | 2 ++ .../javascript/MembershipCandidates.qll | 2 ++ .../javascript/NodeModuleResolutionImpl.qll | 2 ++ .../lib/semmle/javascript/PackageExports.qll | 2 ++ javascript/ql/lib/semmle/javascript/Paths.qll | 2 ++ .../ql/lib/semmle/javascript/PrintAst.qll | 2 ++ .../lib/semmle/javascript/RangeAnalysis.qll | 3 +++ .../semmle/javascript/RestrictedLocations.qll | 2 ++ .../ql/lib/semmle/javascript/Routing.qll | 5 +++++ .../ql/lib/semmle/javascript/SourceMaps.qll | 2 ++ .../lib/semmle/javascript/StandardLibrary.qll | 2 ++ .../semmle/javascript/StringConcatenation.qll | 2 ++ .../ql/lib/semmle/javascript/StringOps.qll | 22 +++++++++++++++++++ .../ql/lib/semmle/javascript/TSConfig.qll | 2 ++ javascript/ql/lib/semmle/javascript/Unit.qll | 2 ++ javascript/ql/lib/semmle/javascript/Util.qll | 2 ++ .../semmle/javascript/ViewComponentInput.qll | 2 ++ .../dataflow/AbstractProperties.qll | 3 +++ .../dataflow/AdditionalTaintSteps.qll | 2 ++ .../dataflow/BackwardExploration.qll | 1 + .../dataflow/ForwardExploration.qll | 1 + .../javascript/dataflow/LocalObjects.qll | 2 ++ .../semmle/javascript/dataflow/Portals.qll | 1 + .../javascript/dataflow/PromisifyFlow.qll | 2 ++ .../javascript/dataflow/TaintTracking.qll | 4 ++++ .../javascript/dataflow/TypeInference.qll | 2 ++ .../javascript/dataflow/TypeTracking.qll | 6 +++++ .../internal/AbstractPropertiesImpl.qll | 2 ++ .../dataflow/internal/AnalyzedParameters.qll | 3 +++ .../dataflow/internal/BarrierGuards.qll | 2 ++ .../internal/BasicExprTypeInference.qll | 2 ++ .../dataflow/internal/CallGraphs.qll | 2 ++ .../internal/DataFlowImplConsistency.qll | 3 +++ .../internal/FunctionWrapperSteps.qll | 2 ++ .../internal/InterModuleTypeInference.qll | 2 ++ .../internal/InterProceduralTypeInference.qll | 2 ++ .../dataflow/internal/PreCallGraphStep.qll | 2 ++ .../internal/PropertyTypeInference.qll | 2 ++ .../dataflow/internal/StepSummary.qll | 3 +++ .../internal/TaintTrackingPrivate.qll | 3 +++ .../internal/VariableTypeInference.qll | 2 ++ .../dataflow/internal/sharedlib/DataFlow.qll | 2 ++ .../internal/sharedlib/DataFlowArg.qll | 3 +++ .../internal/sharedlib/DataFlowImpl.qll | 3 +++ .../internal/sharedlib/DataFlowImplCommon.qll | 3 +++ .../sharedlib/DataFlowImplSpecific.qll | 3 +++ .../internal/sharedlib/FlowSummaryImpl.qll | 3 +++ .../internal/sharedlib/SummaryTypeTracker.qll | 3 +++ .../internal/sharedlib/TaintTracking.qll | 2 ++ .../javascript/dependencies/Dependencies.qll | 2 ++ .../dependencies/FrameworkLibraries.qll | 2 ++ .../semmle/javascript/dependencies/SemVer.qll | 2 ++ .../javascript/endpoints/EndpointNaming.qll | 2 ++ .../javascript/explore/BackwardDataFlow.qll | 1 + .../semmle/javascript/explore/CallGraph.qll | 2 ++ .../javascript/explore/ForwardDataFlow.qll | 1 + .../javascript/filters/ClassifyFiles.qll | 3 +++ .../lib/semmle/javascript/frameworks/AWS.qll | 2 ++ .../javascript/frameworks/ActionsLib.qll | 2 ++ .../semmle/javascript/frameworks/Angular2.qll | 2 ++ .../javascript/frameworks/AngularJS.qll | 3 +++ .../AngularJS/AngularJSExpressions.qll | 2 ++ .../AngularJS/DependencyInjections.qll | 2 ++ .../AngularJS/ServiceDefinitions.qll | 2 ++ .../semmle/javascript/frameworks/Anser.qll | 2 ++ .../semmle/javascript/frameworks/Azure.qll | 2 ++ .../semmle/javascript/frameworks/Babel.qll | 2 ++ .../semmle/javascript/frameworks/Bundling.qll | 2 ++ .../semmle/javascript/frameworks/Cheerio.qll | 2 ++ .../javascript/frameworks/ClassValidator.qll | 2 ++ .../javascript/frameworks/Classnames.qll | 2 ++ .../javascript/frameworks/ClosureLibrary.qll | 2 ++ .../frameworks/CommandLineArguments.qll | 2 ++ .../frameworks/ComposedFunctions.qll | 2 ++ .../semmle/javascript/frameworks/Connect.qll | 2 ++ .../frameworks/ConnectExpressShared.qll | 4 ++++ .../javascript/frameworks/CookieLibraries.qll | 2 ++ .../javascript/frameworks/Credentials.qll | 2 ++ .../javascript/frameworks/CryptoLibraries.qll | 2 ++ .../javascript/frameworks/DateFunctions.qll | 2 ++ .../javascript/frameworks/DigitalOcean.qll | 2 ++ .../javascript/frameworks/DomEvents.qll | 2 ++ .../javascript/frameworks/Emscripten.qll | 2 ++ .../javascript/frameworks/EventEmitter.qll | 3 +++ .../semmle/javascript/frameworks/Execa.qll | 2 ++ .../semmle/javascript/frameworks/Express.qll | 2 ++ .../javascript/frameworks/ExpressModules.qll | 2 ++ .../semmle/javascript/frameworks/Fastify.qll | 2 ++ .../semmle/javascript/frameworks/Files.qll | 2 ++ .../semmle/javascript/frameworks/Firebase.qll | 2 ++ .../javascript/frameworks/FormParsers.qll | 2 ++ .../lib/semmle/javascript/frameworks/GWT.qll | 2 ++ .../semmle/javascript/frameworks/GraphQL.qll | 2 ++ .../lib/semmle/javascript/frameworks/HTTP.qll | 2 ++ .../javascript/frameworks/Handlebars.qll | 2 ++ .../lib/semmle/javascript/frameworks/Hapi.qll | 2 ++ .../javascript/frameworks/HttpFrameworks.qll | 3 +++ .../javascript/frameworks/HttpProxy.qll | 2 ++ .../lib/semmle/javascript/frameworks/JWT.qll | 2 ++ .../lib/semmle/javascript/frameworks/Knex.qll | 2 ++ .../lib/semmle/javascript/frameworks/Koa.qll | 2 ++ .../semmle/javascript/frameworks/LdapJS.qll | 2 ++ .../javascript/frameworks/LiveServer.qll | 2 ++ .../semmle/javascript/frameworks/Markdown.qll | 2 ++ .../semmle/javascript/frameworks/Micro.qll | 2 ++ .../semmle/javascript/frameworks/MooTools.qll | 2 ++ .../lib/semmle/javascript/frameworks/Next.qll | 2 ++ .../semmle/javascript/frameworks/NoSQL.qll | 2 ++ .../semmle/javascript/frameworks/PkgCloud.qll | 2 ++ .../semmle/javascript/frameworks/Prettier.qll | 2 ++ .../javascript/frameworks/Puppeteer.qll | 2 ++ .../semmle/javascript/frameworks/React.qll | 2 ++ .../javascript/frameworks/ReactNative.qll | 2 ++ .../semmle/javascript/frameworks/Request.qll | 2 ++ .../semmle/javascript/frameworks/Restify.qll | 2 ++ .../lib/semmle/javascript/frameworks/RxJS.qll | 2 ++ .../lib/semmle/javascript/frameworks/SQL.qll | 2 ++ .../javascript/frameworks/ServerLess.qll | 2 ++ .../semmle/javascript/frameworks/ShellJS.qll | 2 ++ .../javascript/frameworks/Snapdragon.qll | 2 ++ .../semmle/javascript/frameworks/SocketIO.qll | 2 ++ .../semmle/javascript/frameworks/Spife.qll | 2 ++ .../frameworks/StringFormatters.qll | 2 ++ .../frameworks/SystemCommandExecutors.qll | 2 ++ .../semmle/javascript/frameworks/Testing.qll | 2 ++ .../frameworks/TorrentLibraries.qll | 2 ++ .../javascript/frameworks/Typeahead.qll | 2 ++ .../frameworks/UnderscoreDotString.qll | 2 ++ .../lib/semmle/javascript/frameworks/Vuex.qll | 3 +++ .../javascript/frameworks/XmlParsers.qll | 2 ++ .../data/internal/ApiGraphModelsExport.qll | 2 ++ .../javascript/frameworks/helmet/Helmet.qll | 2 ++ .../semmle/javascript/frameworks/jQuery.qll | 2 ++ .../semmle/javascript/frameworks/xUnit.qll | 2 ++ .../heuristics/AdditionalFrameworks.qll | 2 ++ .../heuristics/AdditionalPromises.qll | 2 ++ .../heuristics/AdditionalRouteHandlers.qll | 2 ++ .../javascript/heuristics/AdditionalSinks.qll | 2 ++ .../heuristics/AdditionalSources.qll | 2 ++ .../heuristics/AdditionalTaintSteps.qll | 2 ++ .../javascript/heuristics/HeuristicSinks.qll | 2 ++ .../heuristics/SyntacticHeuristics.qll | 2 ++ .../lib/semmle/javascript/heuristics/all.qll | 2 ++ .../javascript/internal/BindingInfo.qll | 2 ++ .../javascript/internal/NameResolution.qll | 3 +++ .../javascript/internal/TypeResolution.qll | 3 +++ .../javascript/internal/UnderlyingTypes.qll | 2 ++ .../flow_summaries/AllFlowSummaries.qll | 3 +++ .../javascript/internal/paths/JSPaths.qll | 2 ++ .../internal/paths/PackageJsonEx.qll | 3 +++ .../internal/paths/PathConcatenation.qll | 3 +++ .../internal/paths/PathExprResolver.qll | 3 +++ .../javascript/internal/paths/PathMapping.qll | 2 ++ .../lib/semmle/javascript/linters/ESLint.qll | 2 ++ .../lib/semmle/javascript/linters/JSLint.qll | 2 ++ .../lib/semmle/javascript/linters/Linting.qll | 2 ++ .../javascript/meta/ExtractionMetrics.qll | 3 +++ .../javascript/security/CommonFlowState.qll | 2 ++ ...sPermissiveConfigurationCustomizations.qll | 2 ++ .../CorsPermissiveConfigurationQuery.qll | 2 ++ .../javascript/security/CryptoAlgorithms.qll | 2 ++ .../FunctionalityFromUntrustedSource.qll | 2 ++ .../security/IncompleteBlacklistSanitizer.qll | 2 ++ ...ompleteMultiCharacterSanitizationQuery.qll | 2 ++ ...leteMultiCharacterSanitizationSpecific.qll | 2 ++ .../PasswordInConfigurationFileQuery.qll | 2 ++ .../javascript/security/SensitiveActions.qll | 2 ++ .../javascript/security/TaintedObject.qll | 2 ++ .../security/TaintedObjectCustomizations.qll | 2 ++ .../javascript/security/TaintedUrlSuffix.qll | 2 ++ .../TaintedUrlSuffixCustomizations.qll | 2 ++ .../javascript/security/UselessUseOfCat.qll | 2 ++ .../BrokenCryptoAlgorithmCustomizations.qll | 2 ++ .../BuildArtifactLeakCustomizations.qll | 2 ++ .../CleartextLoggingCustomizations.qll | 2 ++ .../CleartextStorageCustomizations.qll | 2 ++ .../ClientSideUrlRedirectCustomizations.qll | 3 +++ .../dataflow/ClientSideUrlRedirectQuery.qll | 2 ++ .../dataflow/CodeInjectionCustomizations.qll | 2 ++ .../CommandInjectionCustomizations.qll | 2 ++ .../ConditionalBypassCustomizations.qll | 2 ++ ...figurationForCredentialsCustomizations.qll | 2 ++ .../javascript/security/dataflow/DOM.qll | 2 ++ ...ObjectResourceExhaustionCustomizations.qll | 2 ++ .../DeepObjectResourceExhaustionQuery.qll | 2 ++ ...entKindsComparisonBypassCustomizations.qll | 2 ++ .../dataflow/DomBasedXssCustomizations.qll | 2 ++ .../security/dataflow/DomBasedXssQuery.qll | 2 ++ .../dataflow/ExceptionXssCustomizations.qll | 2 ++ .../security/dataflow/ExceptionXssQuery.qll | 2 ++ ...APIUsedWithUntrustedDataCustomizations.qll | 2 ++ .../FileAccessToHttpCustomizations.qll | 2 ++ .../HardcodedCredentialsCustomizations.qll | 2 ++ ...dedDataInterpretedAsCodeCustomizations.qll | 2 ++ .../HardcodedDataInterpretedAsCodeQuery.qll | 2 ++ .../HttpToFileAccessCustomizations.qll | 2 ++ .../dataflow/HttpToFileAccessSpecific.qll | 2 ++ ...ImproperCodeSanitizationCustomizations.qll | 2 ++ ...tmlAttributeSanitizationCustomizations.qll | 2 ++ ...completeHtmlAttributeSanitizationQuery.qll | 2 ++ .../dataflow/IndirectCommandArgument.qll | 2 ++ ...IndirectCommandInjectionCustomizations.qll | 2 ++ .../InsecureDownloadCustomizations.qll | 2 ++ .../dataflow/InsecureDownloadQuery.qll | 2 ++ .../InsecureRandomnessCustomizations.qll | 2 ++ .../InsecureTemporaryFileCustomizations.qll | 2 ++ ...InsufficientPasswordHashCustomizations.qll | 2 ++ .../LoopBoundInjectionCustomizations.qll | 2 ++ .../dataflow/LoopBoundInjectionQuery.qll | 2 ++ .../security/dataflow/MissingRateLimiting.qll | 2 ++ .../dataflow/NosqlInjectionCustomizations.qll | 2 ++ .../security/dataflow/NosqlInjectionQuery.qll | 2 ++ .../PostMessageStarCustomizations.qll | 2 ++ .../dataflow/PropertyInjectionShared.qll | 2 ++ ...otypePollutingAssignmentCustomizations.qll | 2 ++ .../PrototypePollutingAssignmentQuery.qll | 2 ++ .../PrototypePollutionCustomizations.qll | 2 ++ .../dataflow/PrototypePollutionQuery.qll | 2 ++ .../dataflow/ReflectedXssCustomizations.qll | 2 ++ .../RegExpInjectionCustomizations.qll | 2 ++ .../RemotePropertyInjectionCustomizations.qll | 2 ++ .../dataflow/RequestForgeryCustomizations.qll | 2 ++ .../ResourceExhaustionCustomizations.qll | 2 ++ ...ondOrderCommandInjectionCustomizations.qll | 2 ++ .../SecondOrderCommandInjectionQuery.qll | 2 ++ .../ServerSideUrlRedirectCustomizations.qll | 2 ++ ...InjectionFromEnvironmentCustomizations.qll | 2 ++ .../dataflow/SqlInjectionCustomizations.qll | 2 ++ .../StackTraceExposureCustomizations.qll | 2 ++ .../dataflow/StoredXssCustomizations.qll | 2 ++ .../TaintedFormatStringCustomizations.qll | 2 ++ .../dataflow/TaintedFormatStringSpecific.qll | 2 ++ .../dataflow/TaintedPathCustomizations.qll | 2 ++ .../security/dataflow/TaintedPathQuery.qll | 2 ++ .../TemplateObjectInjectionCustomizations.qll | 2 ++ .../dataflow/TemplateObjectInjectionQuery.qll | 2 ++ ...hroughParameterTamperingCustomizations.qll | 2 ++ .../dataflow/UnsafeCodeConstruction.qll | 2 ++ .../UnsafeCodeConstructionCustomizations.qll | 2 ++ .../UnsafeDeserializationCustomizations.qll | 2 ++ ...nsafeDynamicMethodAccessCustomizations.qll | 2 ++ .../UnsafeDynamicMethodAccessQuery.qll | 2 ++ .../UnsafeHtmlConstructionCustomizations.qll | 2 ++ .../dataflow/UnsafeHtmlConstructionQuery.qll | 2 ++ .../UnsafeJQueryPluginCustomizations.qll | 2 ++ ...ShellCommandConstructionCustomizations.qll | 2 ++ ...lidatedDynamicMethodCallCustomizations.qll | 2 ++ .../UnvalidatedDynamicMethodCallQuery.qll | 2 ++ .../security/dataflow/UrlConcatenation.qll | 2 ++ .../dataflow/XmlBombCustomizations.qll | 2 ++ .../dataflow/XpathInjectionCustomizations.qll | 2 ++ .../javascript/security/dataflow/Xss.qll | 2 ++ .../dataflow/XssThroughDomCustomizations.qll | 2 ++ .../security/dataflow/XxeCustomizations.qll | 2 ++ .../dataflow/ZipSlipCustomizations.qll | 2 ++ .../security/dataflow/ZipSlipQuery.qll | 2 ++ .../security/regexp/HostnameRegexp.qll | 2 ++ .../regexp/PolynomialReDoSCustomizations.qll | 2 ++ .../security/regexp/RegExpTreeView.qll | 2 ++ .../ql/lib/utils/test/ConsistencyChecking.qll | 2 ++ .../ql/lib/utils/test/InlineFlowTestUtil.qll | 2 ++ .../ql/lib/utils/test/InlineSummaries.qll | 3 +++ .../ql/lib/utils/test/LegacyDataFlowDiff.qll | 3 +++ .../internal/InlineExpectationsTestImpl.qll | 3 +++ 294 files changed, 642 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/Customizations.qll b/javascript/ql/lib/Customizations.qll index 724d52dcce63..08365d667df7 100644 --- a/javascript/ql/lib/Customizations.qll +++ b/javascript/ql/lib/Customizations.qll @@ -8,5 +8,7 @@ * `FileSystemAccess`, or the `Source` and `Sink` classes associated with the security queries * to model frameworks that are not covered by the standard library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/Declarations/Declarations.qll b/javascript/ql/lib/Declarations/Declarations.qll index 4fb60140af06..eeff76726b9a 100644 --- a/javascript/ql/lib/Declarations/Declarations.qll +++ b/javascript/ql/lib/Declarations/Declarations.qll @@ -2,6 +2,8 @@ * Provides predicates for finding variable references and declarations * in a given function or toplevel. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/Declarations/UnusedVariable.qll b/javascript/ql/lib/Declarations/UnusedVariable.qll index eb02f99444cf..4dc30e39327b 100644 --- a/javascript/ql/lib/Declarations/UnusedVariable.qll +++ b/javascript/ql/lib/Declarations/UnusedVariable.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for the 'js/unused-local-variable' query. */ +overlay[local?] +module; import javascript import LanguageFeatures.UnusedIndexVariable diff --git a/javascript/ql/lib/Expressions/DOMProperties.qll b/javascript/ql/lib/Expressions/DOMProperties.qll index fdb7e6024c27..a3b888aeda70 100644 --- a/javascript/ql/lib/Expressions/DOMProperties.qll +++ b/javascript/ql/lib/Expressions/DOMProperties.qll @@ -1,6 +1,8 @@ /** * Provides predicates for working with the DOM type hierarchy. */ +overlay[local?] +module; import semmle.javascript.Externs diff --git a/javascript/ql/lib/IDEContextual.qll b/javascript/ql/lib/IDEContextual.qll index f26956bcca01..e74d51898e8d 100644 --- a/javascript/ql/lib/IDEContextual.qll +++ b/javascript/ql/lib/IDEContextual.qll @@ -1,6 +1,8 @@ /** * Provides shared predicates related to contextual queries in the code viewer. */ +overlay[local?] +module; import semmle.files.FileSystem private import codeql.util.FileSystem diff --git a/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll b/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll index e8b235eca9b0..c9905d98fccc 100644 --- a/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll +++ b/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll @@ -1,7 +1,7 @@ /** * Provides a predicate for identifying unused index variables in loops. */ -overlay[local] +overlay[local?] module; import javascript diff --git a/javascript/ql/lib/default.qll b/javascript/ql/lib/default.qll index 204a15864c3e..d123ec1a5983 100644 --- a/javascript/ql/lib/default.qll +++ b/javascript/ql/lib/default.qll @@ -3,5 +3,7 @@ * * Provides classes for working with JavaScript programs, as well as JSON, YAML and HTML. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/definitions.qll b/javascript/ql/lib/definitions.qll index 54ad0c3548a6..87018229e926 100644 --- a/javascript/ql/lib/definitions.qll +++ b/javascript/ql/lib/definitions.qll @@ -2,6 +2,8 @@ * Provides classes and predicates related to jump-to-definition links * in the code viewer. */ +overlay[local?] +module; import javascript import IDEContextual diff --git a/javascript/ql/lib/external/ExternalArtifact.qll b/javascript/ql/lib/external/ExternalArtifact.qll index 5d8a2ac9e6ff..c9b6410da602 100644 --- a/javascript/ql/lib/external/ExternalArtifact.qll +++ b/javascript/ql/lib/external/ExternalArtifact.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with external data. */ +overlay[local?] +module; import semmle.javascript.Locations diff --git a/javascript/ql/lib/javascript.qll b/javascript/ql/lib/javascript.qll index ad9cfe009b51..816096fc8275 100644 --- a/javascript/ql/lib/javascript.qll +++ b/javascript/ql/lib/javascript.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JavaScript programs, as well as JSON, YAML and HTML. */ +overlay[local?] +module; import Customizations import semmle.javascript.Aliases diff --git a/javascript/ql/lib/semmle/files/FileSystem.qll b/javascript/ql/lib/semmle/files/FileSystem.qll index 257f38c5e948..9947637b41e6 100644 --- a/javascript/ql/lib/semmle/files/FileSystem.qll +++ b/javascript/ql/lib/semmle/files/FileSystem.qll @@ -1,3 +1,5 @@ /** Provides classes for working with files and folders. */ +overlay[local?] +module; import semmle.javascript.Files diff --git a/javascript/ql/lib/semmle/javascript/Actions.qll b/javascript/ql/lib/semmle/javascript/Actions.qll index a3dd7542ec13..3cde9a914ad3 100644 --- a/javascript/ql/lib/semmle/javascript/Actions.qll +++ b/javascript/ql/lib/semmle/javascript/Actions.qll @@ -4,6 +4,8 @@ * Libraries for modeling GitHub Actions workflow files written in YAML. * See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Aliases.qll b/javascript/ql/lib/semmle/javascript/Aliases.qll index 021cca85120f..9497e0603361 100644 --- a/javascript/ql/lib/semmle/javascript/Aliases.qll +++ b/javascript/ql/lib/semmle/javascript/Aliases.qll @@ -2,6 +2,8 @@ * Provides aliases for commonly used classes that have different names * in the QL libraries for other languages. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Arrays.qll b/javascript/ql/lib/semmle/javascript/Arrays.qll index d85221858866..58a70fe357a8 100644 --- a/javascript/ql/lib/semmle/javascript/Arrays.qll +++ b/javascript/ql/lib/semmle/javascript/Arrays.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript private import semmle.javascript.dataflow.InferredTypes private import semmle.javascript.dataflow.internal.PreCallGraphStep diff --git a/javascript/ql/lib/semmle/javascript/Base64.qll b/javascript/ql/lib/semmle/javascript/Base64.qll index 4f548fe18738..59c1c8fdee51 100644 --- a/javascript/ql/lib/semmle/javascript/Base64.qll +++ b/javascript/ql/lib/semmle/javascript/Base64.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with base64 encoders and decoders. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/BasicBlocks.qll b/javascript/ql/lib/semmle/javascript/BasicBlocks.qll index dfd9c3956b18..e3fd0bc8b140 100644 --- a/javascript/ql/lib/semmle/javascript/BasicBlocks.qll +++ b/javascript/ql/lib/semmle/javascript/BasicBlocks.qll @@ -2,5 +2,7 @@ * Provides classes for working with basic blocks, and predicates for computing * liveness information for local variables. */ +overlay[local?] +module; import internal.BasicBlockInternal::Public diff --git a/javascript/ql/lib/semmle/javascript/CanonicalNames.qll b/javascript/ql/lib/semmle/javascript/CanonicalNames.qll index 87f7c25b36de..1e851e3664d1 100644 --- a/javascript/ql/lib/semmle/javascript/CanonicalNames.qll +++ b/javascript/ql/lib/semmle/javascript/CanonicalNames.qll @@ -1,6 +1,7 @@ /** * Provides classes for working with name resolution of namespaces and types. */ +overlay[local?] deprecated module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/CharacterEscapes.qll b/javascript/ql/lib/semmle/javascript/CharacterEscapes.qll index 5c8dd2bdd06e..ac8281868c4c 100644 --- a/javascript/ql/lib/semmle/javascript/CharacterEscapes.qll +++ b/javascript/ql/lib/semmle/javascript/CharacterEscapes.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about character escapes in literals. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Collections.qll b/javascript/ql/lib/semmle/javascript/Collections.qll index f3e3eb5a61db..648dd752e1fd 100644 --- a/javascript/ql/lib/semmle/javascript/Collections.qll +++ b/javascript/ql/lib/semmle/javascript/Collections.qll @@ -3,6 +3,8 @@ * Currently [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and * [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) are implemented. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.StepSummary diff --git a/javascript/ql/lib/semmle/javascript/Concepts.qll b/javascript/ql/lib/semmle/javascript/Concepts.qll index 70fe76ae5f13..b5d7ddd0d9ee 100644 --- a/javascript/ql/lib/semmle/javascript/Concepts.qll +++ b/javascript/ql/lib/semmle/javascript/Concepts.qll @@ -3,6 +3,8 @@ * access or system command execution, for which individual framework libraries * provide concrete subclasses. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.sharedlib.DataFlowArg diff --git a/javascript/ql/lib/semmle/javascript/DOM.qll b/javascript/ql/lib/semmle/javascript/DOM.qll index 21854c1a9d0e..71f34904b081 100644 --- a/javascript/ql/lib/semmle/javascript/DOM.qll +++ b/javascript/ql/lib/semmle/javascript/DOM.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with DOM elements. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Templating diff --git a/javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll index 96bbea0e55cc..364a0d85b415 100644 --- a/javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll +++ b/javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with defensive programming patterns. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll b/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll index a81e8828d316..1dbdf6980116 100644 --- a/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll +++ b/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with dynamic property accesses. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/EmailClients.qll b/javascript/ql/lib/semmle/javascript/EmailClients.qll index 3f375b4b1252..4a499b59c7a3 100644 --- a/javascript/ql/lib/semmle/javascript/EmailClients.qll +++ b/javascript/ql/lib/semmle/javascript/EmailClients.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript /** diff --git a/javascript/ql/lib/semmle/javascript/GeneratedCode.qll b/javascript/ql/lib/semmle/javascript/GeneratedCode.qll index e045a98f3b07..8f13a3847307 100644 --- a/javascript/ql/lib/semmle/javascript/GeneratedCode.qll +++ b/javascript/ql/lib/semmle/javascript/GeneratedCode.qll @@ -1,6 +1,8 @@ /** * Provides classes for detecting generated code. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Bundling diff --git a/javascript/ql/lib/semmle/javascript/Generators.qll b/javascript/ql/lib/semmle/javascript/Generators.qll index b2b81ef5c882..f8bf45c577dd 100644 --- a/javascript/ql/lib/semmle/javascript/Generators.qll +++ b/javascript/ql/lib/semmle/javascript/Generators.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with generator functions. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.PreCallGraphStep diff --git a/javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll b/javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll index c8a0895e6843..fd3b34a1bbd7 100644 --- a/javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll +++ b/javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with HTML sanitizers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/InclusionTests.qll b/javascript/ql/lib/semmle/javascript/InclusionTests.qll index 3d9921bf6ff2..aa0bd8a2df3e 100644 --- a/javascript/ql/lib/semmle/javascript/InclusionTests.qll +++ b/javascript/ql/lib/semmle/javascript/InclusionTests.qll @@ -1,6 +1,8 @@ /** * Contains classes for recognizing array and string inclusion tests. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/JsonParsers.qll b/javascript/ql/lib/semmle/javascript/JsonParsers.qll index f447f0e41c9e..cf7a06ef09ce 100644 --- a/javascript/ql/lib/semmle/javascript/JsonParsers.qll +++ b/javascript/ql/lib/semmle/javascript/JsonParsers.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSON parsers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/JsonSchema.qll b/javascript/ql/lib/semmle/javascript/JsonSchema.qll index a298abfd2dd7..dd7c50875578 100644 --- a/javascript/ql/lib/semmle/javascript/JsonSchema.qll +++ b/javascript/ql/lib/semmle/javascript/JsonSchema.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with JSON schema libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll index bb1b23610c94..d36911b299c0 100644 --- a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll +++ b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSON serializers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll index b294cb7ca3ab..e7a89ebb32ae 100644 --- a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll +++ b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll @@ -1,6 +1,8 @@ /** * Provides classes for recognizing membership tests. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll index 467e14aa74fb..ac94c153baa3 100644 --- a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll +++ b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll @@ -3,6 +3,8 @@ * * Provides predicates for modeling Node.js module resolution. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/PackageExports.qll b/javascript/ql/lib/semmle/javascript/PackageExports.qll index b4032980688f..56c2366b8246 100644 --- a/javascript/ql/lib/semmle/javascript/PackageExports.qll +++ b/javascript/ql/lib/semmle/javascript/PackageExports.qll @@ -3,6 +3,8 @@ * * Provides predicates for working with values exported from a package. */ +overlay[local?] +module; import javascript private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/Paths.qll b/javascript/ql/lib/semmle/javascript/Paths.qll index 38c24a1b8e90..1a98c477f575 100644 --- a/javascript/ql/lib/semmle/javascript/Paths.qll +++ b/javascript/ql/lib/semmle/javascript/Paths.qll @@ -2,6 +2,8 @@ * Provides classes for working with file system paths and program expressions * that denote them. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/PrintAst.qll b/javascript/ql/lib/semmle/javascript/PrintAst.qll index b4f40d99f235..7bc79c5509e5 100644 --- a/javascript/ql/lib/semmle/javascript/PrintAst.qll +++ b/javascript/ql/lib/semmle/javascript/PrintAst.qll @@ -5,6 +5,8 @@ * extend `PrintAstConfiguration` and override `shouldPrint` to hold for only the elements * you wish to view the AST for. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll b/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll index a385df662ce2..e0713f4f31b1 100644 --- a/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll +++ b/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript /* diff --git a/javascript/ql/lib/semmle/javascript/RestrictedLocations.qll b/javascript/ql/lib/semmle/javascript/RestrictedLocations.qll index 47ee41a42357..2276f496813a 100644 --- a/javascript/ql/lib/semmle/javascript/RestrictedLocations.qll +++ b/javascript/ql/lib/semmle/javascript/RestrictedLocations.qll @@ -1,4 +1,6 @@ /** Provides classes for restricting the locations reported for program elements. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Routing.qll b/javascript/ql/lib/semmle/javascript/Routing.qll index 8fe9f79d8623..2b051b9c6894 100644 --- a/javascript/ql/lib/semmle/javascript/Routing.qll +++ b/javascript/ql/lib/semmle/javascript/Routing.qll @@ -2,6 +2,8 @@ * A model of routing trees, describing the composition of route handlers and middleware functions * in a web server application. See `Routing::Node` for more details. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps @@ -279,6 +281,7 @@ module Routing { /** * Holds if `node` has processed the incoming request strictly prior to this node. */ + overlay[caller?] pragma[inline] predicate isGuardedByNode(Node node) { this.isGuardedByNodeInternal(pragma[only_bind_out](node)) @@ -287,6 +290,7 @@ module Routing { /** * Holds if the middleware corresponding to `node` has processed the incoming request strictly prior to this node. */ + overlay[caller?] pragma[inline] predicate isGuardedBy(DataFlow::Node node) { this.isGuardedByNode(getNode(node)) } @@ -894,6 +898,7 @@ module Routing { * Gets a node that is stored in the given access path on this route handler parameter, either * during execution of this router handler, or in one of the preceding ones. */ + overlay[caller?] pragma[inline] DataFlow::Node getValueFromAccessPath(string path) { exists(int i, Node predecessor | diff --git a/javascript/ql/lib/semmle/javascript/SourceMaps.qll b/javascript/ql/lib/semmle/javascript/SourceMaps.qll index 21fa71121324..e64e3db2b39f 100644 --- a/javascript/ql/lib/semmle/javascript/SourceMaps.qll +++ b/javascript/ql/lib/semmle/javascript/SourceMaps.qll @@ -1,4 +1,6 @@ /** Provides a class for representing source maps. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll index 5104469635d7..c72fc0d8f8ba 100644 --- a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll +++ b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll @@ -1,4 +1,6 @@ /** Provides classes for working with standard library objects. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/StringConcatenation.qll b/javascript/ql/lib/semmle/javascript/StringConcatenation.qll index d4039cbf41a4..ca6485cc5b4e 100644 --- a/javascript/ql/lib/semmle/javascript/StringConcatenation.qll +++ b/javascript/ql/lib/semmle/javascript/StringConcatenation.qll @@ -1,6 +1,8 @@ /** * Provides predicates for analyzing string concatenations and their operands. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/StringOps.qll b/javascript/ql/lib/semmle/javascript/StringOps.qll index f2b7f3eb9aa7..6c7bb721b1ad 100644 --- a/javascript/ql/lib/semmle/javascript/StringOps.qll +++ b/javascript/ql/lib/semmle/javascript/StringOps.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for reasoning about string-manipulating expressions. */ +overlay[local?] +module; import javascript @@ -387,6 +389,7 @@ module StringOps { * ``` */ class ConcatenationNode extends DataFlow::Node { + overlay[caller?] pragma[inline] ConcatenationNode() { exists(StringConcatenation::getAnOperand(this)) @@ -397,36 +400,42 @@ module StringOps { /** * Gets the `n`th operand of this string concatenation. */ + overlay[caller?] pragma[inline] ConcatenationOperand getOperand(int n) { result = StringConcatenation::getOperand(this, n) } /** * Gets an operand of this string concatenation. */ + overlay[caller?] pragma[inline] ConcatenationOperand getAnOperand() { result = StringConcatenation::getAnOperand(this) } /** * Gets the number of operands of this string concatenation. */ + overlay[caller?] pragma[inline] int getNumOperand() { result = StringConcatenation::getNumOperand(this) } /** * Gets the first operand of this string concatenation. */ + overlay[caller?] pragma[inline] ConcatenationOperand getFirstOperand() { result = StringConcatenation::getFirstOperand(this) } /** * Gets the last operand of this string concatenation */ + overlay[caller?] pragma[inline] ConcatenationOperand getLastOperand() { result = StringConcatenation::getLastOperand(this) } /** * Holds if this only acts as a string coercion, such as `"" + x`. */ + overlay[caller?] pragma[inline] predicate isCoercion() { StringConcatenation::isCoercion(this) } @@ -435,6 +444,7 @@ module StringOps { * it is a concatenation operator that is not itself the immediate operand to * another concatenation operator. */ + overlay[caller?] pragma[inline] predicate isRoot() { StringConcatenation::isRoot(this) } @@ -442,18 +452,21 @@ module StringOps { * Holds if this is a leaf in the concatenation tree, that is, it is not * itself a concatenation. */ + overlay[caller?] pragma[inline] predicate isLeaf() { not exists(StringConcatenation::getAnOperand(this)) } /** * Gets the root of the concatenation tree in which this is an operator. */ + overlay[caller?] pragma[inline] ConcatenationRoot getRoot() { result = StringConcatenation::getRoot(this) } /** * Gets the enclosing concatenation in which this is an operand, if any. */ + overlay[caller?] pragma[inline] Concatenation getParentConcatenation() { this = StringConcatenation::getAnOperand(result) } @@ -462,6 +475,7 @@ module StringOps { * * For example, `z` is the last leaf in `x + y + z`. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getLastLeaf() { result = StringConcatenation::getLastOperand*(this) } @@ -470,6 +484,7 @@ module StringOps { * * For example, `x` is the first leaf in `x + y + z`. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getFirstLeaf() { result = StringConcatenation::getFirstOperand*(this) } @@ -479,6 +494,7 @@ module StringOps { * * For example, `y` is the previous leaf from `z` in `x + y + z`. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getPreviousLeaf() { adjacentLeaves(result, this) } @@ -488,6 +504,7 @@ module StringOps { * * For example, `y` is the next leaf from `x` in `x + y + z`. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getNextLeaf() { adjacentLeaves(this, result) } } @@ -507,6 +524,7 @@ module StringOps { * See `ConcatenationNode` for more information. */ class Concatenation extends ConcatenationNode { + overlay[caller?] pragma[inline] Concatenation() { exists(StringConcatenation::getAnOperand(this)) } } @@ -524,6 +542,7 @@ module StringOps { * See `ConcatenationNode` for more information. */ class ConcatenationOperand extends ConcatenationNode { + overlay[caller?] pragma[inline] ConcatenationOperand() { this = StringConcatenation::getAnOperand(_) } } @@ -541,12 +560,14 @@ module StringOps { * See `ConcatenationNode` for more information. */ class ConcatenationRoot extends Concatenation { + overlay[caller?] pragma[inline] ConcatenationRoot() { this.isRoot() } /** * Gets a leaf in this concatenation tree that this node is the root of. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getALeaf() { this = StringConcatenation::getRoot(result) } @@ -606,6 +627,7 @@ module StringOps { * See `ConcatenationNode` for more information. */ class ConcatenationLeaf extends ConcatenationOperand { + overlay[caller?] pragma[inline] ConcatenationLeaf() { this.isLeaf() } } diff --git a/javascript/ql/lib/semmle/javascript/TSConfig.qll b/javascript/ql/lib/semmle/javascript/TSConfig.qll index c10177e5fe24..2d5c2e6ae919 100644 --- a/javascript/ql/lib/semmle/javascript/TSConfig.qll +++ b/javascript/ql/lib/semmle/javascript/TSConfig.qll @@ -1,6 +1,8 @@ /** * Provides a class for working with `tsconfig.json` files. */ +overlay[local?] +module; private import javascript private import semmle.javascript.internal.paths.PathMapping diff --git a/javascript/ql/lib/semmle/javascript/Unit.qll b/javascript/ql/lib/semmle/javascript/Unit.qll index 83a4a03321d9..e31457eae1aa 100644 --- a/javascript/ql/lib/semmle/javascript/Unit.qll +++ b/javascript/ql/lib/semmle/javascript/Unit.qll @@ -1,3 +1,5 @@ /** Provides the `Unit` class. */ +overlay[local?] +module; import codeql.util.Unit diff --git a/javascript/ql/lib/semmle/javascript/Util.qll b/javascript/ql/lib/semmle/javascript/Util.qll index 701ef2b58311..ef3784e2e384 100644 --- a/javascript/ql/lib/semmle/javascript/Util.qll +++ b/javascript/ql/lib/semmle/javascript/Util.qll @@ -1,6 +1,8 @@ /** * Provides general-purpose utility predicates. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll b/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll index 43cd337685db..411eb24dc6b9 100644 --- a/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll +++ b/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll @@ -1,6 +1,8 @@ /** * Provides a classes and predicates for contributing to the `view-component-input` threat model. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll b/javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll index e9d05d56e26a..dbb589efb33c 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.internal.AbstractValuesImpl private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/dataflow/AdditionalTaintSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/AdditionalTaintSteps.qll index a0752d768fa5..41b8cb9cfe2b 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/AdditionalTaintSteps.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/AdditionalTaintSteps.qll @@ -1,6 +1,8 @@ /** * Note: The contents of this file are exposed with the `TaintTracking::` prefix, via an import in `TaintTracking.qll`. */ +overlay[local?] +module; private import javascript private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll b/javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll index bc527b500c96..df0ce747a56b 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll @@ -1,6 +1,7 @@ /** * Alias for the library `semmle.javascript.explore.BackwardDataFlow`. */ +overlay[local?] deprecated module; import semmle.javascript.explore.BackwardDataFlow diff --git a/javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll b/javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll index 9b9fe218f09d..d96d4756526e 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll @@ -1,6 +1,7 @@ /** * Alias for the library `semmle.javascript.explore.ForwardDataFlow`. */ +overlay[local?] deprecated module; import semmle.javascript.explore.ForwardDataFlow diff --git a/javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll b/javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll index 621d18fb472e..bab76c61d6f1 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll @@ -1,6 +1,8 @@ /** * Provides classes for the local objects that the dataflow library can reason about soundly. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Portals.qll b/javascript/ql/lib/semmle/javascript/dataflow/Portals.qll index d8f29c707a60..6f76e45adf91 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Portals.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Portals.qll @@ -11,6 +11,7 @@ * * The API of this library is not stable yet and may change. */ +overlay[local?] deprecated module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/dataflow/PromisifyFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/PromisifyFlow.qll index 4389a3d031a6..9f38895d5581 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/PromisifyFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/PromisifyFlow.qll @@ -3,6 +3,8 @@ * This ensures that when you call a promisified user-defined function, * arguments flow to the original function's parameters. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.AdditionalFlowSteps diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll index 862cf1b84274..077c5c106935 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll @@ -9,6 +9,8 @@ * specified, and conversely certain nodes or edges can be designated as taint * _sanitizers_ that block flow. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps @@ -1103,6 +1105,7 @@ module TaintTracking { * * This includes steps between synthesized nodes generated by flow summaries. */ + overlay[caller?] pragma[inline] predicate defaultTaintStep(DataFlow::Node node1, DataFlow::Node node2) { TaintTrackingPrivate::defaultAdditionalTaintStep(node1, node2) @@ -1111,6 +1114,7 @@ module TaintTracking { /** * Holds if `node` is seen as a barrier for taint-tracking. */ + overlay[caller?] pragma[inline] predicate defaultSanitizer(DataFlow::Node node) { TaintTrackingPrivate::defaultTaintSanitizer(node) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll index a5e686a90c25..caafff44e769 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll @@ -24,6 +24,8 @@ * the sense that all expressions whole value derives (directly or indirectly) from a property * read are marked as indefinite. */ +overlay[local?] +module; private import javascript import AbstractValues diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll index e4c8f162972a..16072670da60 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll @@ -5,6 +5,8 @@ * for tracking certain types interprocedurally without computing which source * a given value came from. */ +overlay[local?] +module; private import javascript private import internal.FlowSteps @@ -136,6 +138,7 @@ class TypeTracker extends TTypeTracker { * Gets the summary that corresponds to having taken a forwards * heap and/or inter-procedural step from `pred` to `succ`. */ + overlay[caller?] pragma[inline] TypeTracker step(DataFlow::SourceNode pred, DataFlow::SourceNode succ) { exists(StepSummary summary | @@ -168,6 +171,7 @@ class TypeTracker extends TTypeTracker { * } * ``` */ + overlay[caller?] pragma[inline] TypeTracker smallstep(DataFlow::Node pred, DataFlow::Node succ) { exists(StepSummary summary | @@ -293,6 +297,7 @@ class TypeBackTracker extends TTypeBackTracker { * Gets the summary that corresponds to having taken a backwards * heap and/or inter-procedural step from `succ` to `pred`. */ + overlay[caller?] pragma[inline] TypeBackTracker step(DataFlow::SourceNode pred, DataFlow::SourceNode succ) { exists(StepSummary summary | @@ -325,6 +330,7 @@ class TypeBackTracker extends TTypeBackTracker { * } * ``` */ + overlay[caller?] pragma[inline] TypeBackTracker smallstep(DataFlow::Node pred, DataFlow::Node succ) { exists(StepSummary summary | diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll index 6d86e7ea3f25..f1f729dcf798 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll @@ -3,6 +3,8 @@ * * Provides the internal representation of abstract properties and related predicates. */ +overlay[local?] +module; import javascript private import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll index b632c0a12e2d..7354ec6707c2 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import VariableTypeInference diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/BarrierGuards.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/BarrierGuards.qll index 6dd0ebf0bb1c..b55527de1176 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/BarrierGuards.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/BarrierGuards.qll @@ -3,6 +3,8 @@ * * This version considers all barrier guards to be relevant. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.AccessPaths diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll index f6474ff31867..fb10e74aa9b3 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll @@ -4,6 +4,8 @@ * Provides classes implementing type inference for most expressions, except for variable * and property accesses. */ +overlay[local?] +module; private import javascript private import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll index cc4c883381ea..bcc90bec37dc 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -1,6 +1,8 @@ /** * Internal predicates for computing the call graph. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.StepSummary diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowImplConsistency.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowImplConsistency.qll index e5ce83d86c85..a5d3407185b8 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowImplConsistency.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowImplConsistency.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import codeql.dataflow.internal.DataFlowImplConsistency private import sharedlib.DataFlowArg diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll index dda1ac7ae34f..7058729f053d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll @@ -1,4 +1,6 @@ /** Provides predicates for tracking functions through wrapper functions. */ +overlay[local?] +module; private import javascript private import FlowSteps as FlowSteps diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll index 3134d76d8f16..ddde8232d59d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll @@ -3,6 +3,8 @@ * * Provides classes implementing type inference across imports. */ +overlay[local?] +module; private import javascript private import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll index 80de3cb64fdd..cc0ae3264b73 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll @@ -3,6 +3,8 @@ * * Provides classes implementing type inference across function calls. */ +overlay[local?] +module; private import javascript import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll index a1720d122369..41a156835156 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll @@ -2,6 +2,8 @@ * Provides an extension point for contributing flow edges prior * to call graph construction and type tracking. */ +overlay[local?] +module; private import javascript private import semmle.javascript.Unit diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll index 83b23871222b..e5f8e8405d3d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll @@ -3,6 +3,8 @@ * * Provides classes implementing type inference for properties. */ +overlay[local?] +module; private import javascript import semmle.javascript.dataflow.AbstractProperties diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll index fed492074b6a..a7e79c50ca20 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript private import semmle.javascript.dataflow.TypeTracking private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/TaintTrackingPrivate.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/TaintTrackingPrivate.qll index 548d06ef64f5..8ea0d82ebd01 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/TaintTrackingPrivate.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/TaintTrackingPrivate.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.internal.DataFlowPrivate private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll index bbbd967fda80..6dbb87138c73 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll @@ -3,6 +3,8 @@ * * Provides classes implementing type inference for variables. */ +overlay[local?] +module; private import javascript private import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlow.qll index d9e711ee07a8..26fe56c39b1f 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlow.qll @@ -1,4 +1,6 @@ /** Provides the instantiation of the shared data flow library. */ +overlay[local?] +module; private import semmle.javascript.Locations private import codeql.dataflow.DataFlow diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll index c911461788dc..c4591d355a78 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import DataFlowImplSpecific private import codeql.dataflow.DataFlow as SharedDataFlow diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImpl.qll index 3ddcb693f540..37e90e8236aa 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImpl.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImpl.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import codeql.dataflow.internal.DataFlowImpl private import DataFlowArg diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplCommon.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplCommon.qll index 62188d47b809..ce861c45f653 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplCommon.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplCommon.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import DataFlowArg private import codeql.dataflow.internal.DataFlowImplCommon diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplSpecific.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplSpecific.qll index a8b541c1b318..66ccb42b74ae 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplSpecific.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript // This file provides the input to FlowSummaryImpl.qll, which is shared via identical-files.json. diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/FlowSummaryImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/FlowSummaryImpl.qll index bf370eb9a271..707c0db5705e 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/FlowSummaryImpl.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/FlowSummaryImpl.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import codeql.dataflow.internal.FlowSummaryImpl private import DataFlowArg diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll index c9acd77db1a4..98926f1b0008 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import codeql.typetracking.internal.SummaryTypeTracker private import semmle.javascript.dataflow.internal.DataFlowPrivate as DataFlowPrivate diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/TaintTracking.qll index e2215a8afc32..eb9c6e49a189 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/TaintTracking.qll @@ -1,4 +1,6 @@ /** Provides the instantiation of the shared taint tracking library. */ +overlay[local?] +module; private import semmle.javascript.Locations private import codeql.dataflow.TaintTracking diff --git a/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll b/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll index 8ca2add4a274..f3f8ea9334ea 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll @@ -2,6 +2,8 @@ * Provides classes for modeling dependencies such as NPM packages * and framework libraries. */ +overlay[local?] +module; import javascript private import FrameworkLibraries diff --git a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll index 9ff96a58fdc6..ca4ece83d02b 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll @@ -25,6 +25,8 @@ * (for example `Bootstrap` and `React`), while other frameworks have * more complex rules for recognizing instances (for example `MooTools`). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll b/javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll index 1d091e9219c9..531cd95bd759 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll @@ -1,6 +1,8 @@ /** * Provides classes for working SemVer (Semantic Versioning). */ +overlay[local?] +module; import semmle.javascript.dependencies.Dependencies diff --git a/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll b/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll index 8fcb83729c48..ffdc1228fe7e 100644 --- a/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll +++ b/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll @@ -27,6 +27,8 @@ * In these cases, we try to make up human-readable names for the endpoints. * We make an effort to make these unambiguous in practice, though this is not always guaranteed. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll b/javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll index 18b7c27a2db2..9773e6e5cfe0 100644 --- a/javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll @@ -12,6 +12,7 @@ * Backward exploration in particular does not scale on non-trivial code bases and hence is of limited * usefulness as it stands. */ +overlay[local?] deprecated module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/explore/CallGraph.qll b/javascript/ql/lib/semmle/javascript/explore/CallGraph.qll index 4b7853245603..260408c99d14 100644 --- a/javascript/ql/lib/semmle/javascript/explore/CallGraph.qll +++ b/javascript/ql/lib/semmle/javascript/explore/CallGraph.qll @@ -21,6 +21,8 @@ * * NOTE: This library should only be used for debugging and exploration, not in production code. */ +overlay[local?] +module; import javascript private import DataFlow diff --git a/javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll b/javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll index 9d435d067b2e..c99609daca4c 100644 --- a/javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll @@ -10,6 +10,7 @@ * * NOTE: This library should only be used for debugging and exploration, not in production code. */ +overlay[local?] deprecated module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll b/javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll index 8d392bc04482..89f66baff391 100644 --- a/javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll +++ b/javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll @@ -3,6 +3,8 @@ * generated code, test code, externs declarations, library code or * template code. */ +overlay[local?] +module; import semmle.javascript.GeneratedCode import semmle.javascript.frameworks.Testing @@ -100,6 +102,7 @@ predicate isTemplateFile(File f) { * - `"library"`: `f` contains library code; * - `"template"`: `f` contains template code. */ +overlay[caller?] pragma[inline] predicate classify(File f, string category) { isGeneratedCodeFile(f) and category = "generated" diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll index 1eac5888b955..90700b397a4c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [AWS-SDK](https://aws.amazon.com/sdk-for-node-js/) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ActionsLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/ActionsLib.qll index b0b26560ff29..71b1ab3d9d69 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ActionsLib.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ActionsLib.qll @@ -1,6 +1,8 @@ /** * Contains models for `@actions/core` related libraries. */ +overlay[local?] +module; private import javascript private import semmle.javascript.security.dataflow.IndirectCommandInjectionCustomizations diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll index 9fd24c81a4a4..335a7b397c14 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Angular (also known as Angular 2.x) applications. */ +overlay[local?] +module; private import javascript private import semmle.javascript.security.dataflow.DomBasedXssCustomizations diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll index a90e1dd4995e..727b2d4224fb 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + /** * Provides classes for working with AngularJS (also known as Angular 1.x) * applications. diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll index 29d7fe3bdf66..a74a5c0c7847 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll @@ -6,6 +6,8 @@ * NOTE: The API of this library is not stable yet and may change in * the future. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll index 621156b19f89..7e5e8fab6904 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll @@ -6,6 +6,8 @@ * NOTE: The API of this library is not stable yet and may change in * the future. */ +overlay[local?] +module; import javascript private import AngularJS diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll index ae8d3b7d9c5f..3a58fcd37b48 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll @@ -11,6 +11,8 @@ * NOTE: The API of this library is not stable yet and may change in * the future. */ +overlay[local?] +module; import javascript private import AngularJS diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Anser.qll b/javascript/ql/lib/semmle/javascript/frameworks/Anser.qll index 77525689fa44..34fe4a63b318 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Anser.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Anser.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with applications using [anser](https://www.npmjs.com/package/anser). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Azure.qll b/javascript/ql/lib/semmle/javascript/frameworks/Azure.qll index 1527b655eddf..d9a6ecb9b6a4 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Azure.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Azure.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Azure](https://github.com/Azure/azure-sdk-for-node) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll index 9ca47fb47276..24cc9d6f3b25 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Babel, `.babelrc` files and Babel plugins. */ +overlay[local?] +module; import javascript private import semmle.javascript.internal.paths.PathMapping diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll b/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll index 314a6343c9f0..7049ad8665e8 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for detecting files generated by popular module bundlers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll index fdc820861b14..44d5ed840915 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll @@ -1,6 +1,8 @@ /** * Provides a model of `cheerio`, a server-side DOM manipulation library with a jQuery-like API. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.dataflow.DomBasedXssCustomizations diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll index 8b2ef364054f..7da85a9540a7 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll @@ -1,6 +1,8 @@ /** * Provides predicates for reasoning about sanitization via the `class-validator` library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll b/javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll index b5ae5d275692..27c92237e666 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll @@ -1,6 +1,8 @@ /** * Provides taint steps modeling flow through the `classnames` and `clsx` libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll index ef69d2a3c3fb..89a38bbbb63a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll @@ -1,6 +1,8 @@ /** * Provides models for miscellaneous utility functions in the closure standard library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CommandLineArguments.qll b/javascript/ql/lib/semmle/javascript/frameworks/CommandLineArguments.qll index cd8fa34a08eb..5d09cd9cb14b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CommandLineArguments.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CommandLineArguments.qll @@ -1,4 +1,6 @@ /** Provides modeling for parsed command line arguments. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll b/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll index 170eca4996c7..f6468e9e2478 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about composed functions. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll index f6ac5854f4d7..62a34186b023 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Connect](https://github.com/senchalabs/connect) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll b/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll index 87956ef38c85..98f38b2e136d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll @@ -3,6 +3,8 @@ * [Connect](https://github.com/senchalabs/connect) and * [Express](https://expressjs.com) applications. */ +overlay[local?] +module; import javascript @@ -82,6 +84,7 @@ module ConnectExpressShared { * * `kind` is one of: "error", "request", "response", "next". */ + overlay[caller?] pragma[inline] DataFlow::ParameterNode getRouteParameterHandlerParameter( DataFlow::FunctionNode routeHandler, string kind @@ -96,6 +99,7 @@ module ConnectExpressShared { * * `kind` is one of: "error", "request", "response", "next". */ + overlay[caller?] pragma[inline] DataFlow::ParameterNode getRouteHandlerParameter(DataFlow::FunctionNode routeHandler, string kind) { if routeHandler.getNumParameter() = 4 diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll index cdb411927225..d200c450688b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about cookies. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll index 35119a7d8b8f..48b0a3ee602a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll @@ -2,6 +2,8 @@ * Provides a class for modeling expressions used to supply * credentials. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 9cc76b5f5b8c..f2ba9ce0fc7a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling cryptographic libraries. */ +overlay[local?] +module; import javascript import semmle.javascript.Concepts::Cryptography diff --git a/javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll b/javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll index c75f7148f507..98b24787e5df 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll @@ -1,4 +1,6 @@ /** Provides taint steps modeling flow through date-manipulation libraries. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll b/javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll index 60d96a937c9c..06a9935b6c21 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [DigitalOcean](https://www.npmjs.com/package/digitalocean) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll b/javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll index 7fb13d56f08e..effcccbb9454 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll @@ -1,6 +1,8 @@ /** * Provides predicates for reasoning about events from the DOM that introduce tainted data. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll b/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll index 6d5752f769bc..df5f28bdc8cb 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Emscripten-generated code. */ +overlay[local?] +module; import javascript import semmle.javascript.GeneratedCode diff --git a/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll b/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll index f466d96dd9de..8b08275dc53a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript module EventEmitter { diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Execa.qll b/javascript/ql/lib/semmle/javascript/frameworks/Execa.qll index 2ef2fcde3868..5704429c42e2 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Execa.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Execa.qll @@ -1,6 +1,8 @@ /** * Models the `execa` library in terms of `FileSystemAccess` and `SystemCommandExecution`. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Express.qll b/javascript/ql/lib/semmle/javascript/frameworks/Express.qll index be3cb7b1ccb8..8b274cf2d483 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Express.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Express.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Express](https://expressjs.com) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.ExpressModules diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll b/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll index 77c7a455b41b..e611c7704541 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll @@ -1,6 +1,8 @@ /** * Models of npm modules that are used with Express servers. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll index 26dde3fc78bd..e1e190f98473 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Fastify](https://www.fastify.dev/) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll index 30f07396dccd..51f49146046c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with file system libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll b/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll index 51e465ef908b..e0dc12d5c747 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for reasoning about code using the Firebase API. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll index 26e0d4fe94f6..9f09417c74fc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling the server-side form/file parsing libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll b/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll index 7fa72c9a9f04..6da39b270a8a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with GWT-generated code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll index 98b7c2b89f73..c2cdb28e3061 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with GraphQL connectors. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll b/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll index 2d068d6b4bf6..6bced8aafc90 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling common HTTP concepts. */ +overlay[local?] +module; import javascript private import semmle.javascript.DynamicPropertyAccess diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll b/javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll index 56fb1fe20ef1..426179687961 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Handlebars code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index a6dbf40d1e06..4e08bc731d13 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Hapi](https://hapijs.com/) servers. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll index 8e91230d3b21..23aacd31db06 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import semmle.javascript.frameworks.Express import semmle.javascript.frameworks.Hapi import semmle.javascript.frameworks.Koa diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll index d5d890b8b83e..9f7f6436a876 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with the [http-proxy](https://www.npmjs.com/package/http-proxy) library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/JWT.qll b/javascript/ql/lib/semmle/javascript/frameworks/JWT.qll index a9f47a2b6b9f..55a496c02411 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/JWT.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/JWT.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JWT libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll index 923df27bd501..84caa889b82d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with [knex](https://knexjs.org). */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Koa.qll b/javascript/ql/lib/semmle/javascript/frameworks/Koa.qll index c9b4403671d1..01a07c171e83 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Koa.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Koa.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Koa](https://koajs.com) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll index 1118f05b5065..f43b427955a6 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [LDAPjs](https://www.npmjs.com/package/ldapjs) */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll index 5a8075ed366a..729e43ddb7d9 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling the [live-server](https://npmjs.com/package/live-server) package. */ +overlay[local?] +module; import javascript private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpressShared as ConnectExpressShared diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll index 344bdc2a40fc..4b8ec89814f1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling common markdown parsers and generators. */ +overlay[local?] +module; import semmle.javascript.Unit import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Micro.qll b/javascript/ql/lib/semmle/javascript/frameworks/Micro.qll index 0db7b438b7d0..6f37766f2300 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Micro.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Micro.qll @@ -1,6 +1,8 @@ /** * Provides a model of the `micro` NPM package. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll b/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll index c1b4811e889f..90ba42ae8858 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with MooTools code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll index 551d325f26af..27e7fb1bcbda 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for reasoning about [Next.js](https://www.npmjs.com/package/next). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll index aeae1afcac30..5b122f636e91 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with NoSQL libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll b/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll index e7431c754dc9..92467a36cfae 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [pkgcloud](https://github.com/pkgcloud/pkgcloud) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll index 1277c1ee133b..1f0f11b2e096 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with the [prettier](https://www.npmjs.com/package/prettier) library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll index 59bb2fc2b137..fe42aac907e2 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for reasoning about [puppeteer](https://www.npmjs.com/package/puppeteer). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/React.qll b/javascript/ql/lib/semmle/javascript/frameworks/React.qll index d55ace8636df..734685282c8e 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/React.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/React.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with React and Preact code. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll b/javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll index a64edda01e99..10578a7b26dc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [React Native](https://facebook.github.io/react-native) code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Request.qll b/javascript/ql/lib/semmle/javascript/frameworks/Request.qll index 3551da6f0c13..3ba0f3a2dfcc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Request.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Request.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [request](https://github.com/request/request) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll index 0adbefc04e8d..e7ee72068683 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Restify](https://restify.com/) servers. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll index e95999128659..5c00be8ec62d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll @@ -1,6 +1,8 @@ /** * Provides taint steps modeling flow through `rxjs` Observable objects. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll index 9d106251a211..eac5618ea604 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with SQL connectors. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll b/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll index 140797dd5db1..1a5965e0d623 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll @@ -3,6 +3,8 @@ * E.g. [AWS](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html) or [serverless](https://npmjs.com/package/serverless) * In particular a `RemoteFlowSource` is added for AWS, Alibaba, and serverless. */ +overlay[local?] +module; import javascript private import codeql.serverless.ServerLess diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll index fc0e366df4b8..0ed4745256f1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll @@ -3,6 +3,8 @@ * * https://www.npmjs.com/package/shelljs */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll index 6f460a842ffc..4ab30594b751 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with applications using [snapdragon](https://www.npmjs.com/package/snapdragon). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll index cde7ec561240..4d58b0ecd078 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [socket.io](https://socket.io). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll b/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll index f79a6f11eae9..78756afb1134 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Spife](https://github.com/npm/spife) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll b/javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll index d729f457ef78..422713eac950 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling string formatting libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll b/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll index 20baafa04755..3b48a3226947 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll @@ -2,6 +2,8 @@ * Provides concrete classes for data-flow nodes that execute an * operating system command, for instance by spawning a new process. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll b/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll index 248d41062076..c81fe3edb558 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JavaScript testing frameworks. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.TestingCustomizations diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll index 29c100234bf9..7837e67f7331 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling Torrent libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll b/javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll index 7d7a9b107aaa..a2f43aed738a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with typeahead.js code (https://www.npmjs.com/package/typeahead.js). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/UnderscoreDotString.qll b/javascript/ql/lib/semmle/javascript/frameworks/UnderscoreDotString.qll index abb51b978bc0..790aec62795b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/UnderscoreDotString.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/UnderscoreDotString.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling data flow behavior of the Underscore.string library (https://www.npmjs.com/package/underscore.string). */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.AdditionalFlowInternal diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll index 49a9ded864b6..326513914db3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with the `vuex` library. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps @@ -394,6 +396,7 @@ module Vuex { } /** Holds if the two files are considered to be part of the same Vuex app. */ + overlay[caller?] pragma[inline] predicate areFilesInSameVuexApp(File a, File b) { not exists(PackageJson pkg) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll index c0a783c17644..fbe895d8383b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with XML parser APIs. */ +overlay[local?] +module; private import javascript as JS private import JS::DataFlow as DataFlow diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExport.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExport.qll index c79b1ec80e28..15609cb36363 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExport.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExport.qll @@ -1,6 +1,8 @@ /** * Contains an extension of `GraphExport` that relies on API graph specific functionality. */ +overlay[local?] +module; private import ApiGraphModels as Shared private import codeql.mad.dynamic.GraphExport diff --git a/javascript/ql/lib/semmle/javascript/frameworks/helmet/Helmet.qll b/javascript/ql/lib/semmle/javascript/frameworks/helmet/Helmet.qll index 375e87e96466..031c5ceaebc5 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/helmet/Helmet.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/helmet/Helmet.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Helmet */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll index 70beadbfa573..f9b07e2bb5f0 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with jQuery code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll b/javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll index be64f243e46f..9e8d640ba48b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with xUnit.js tests. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll index b02863b5a4b7..46f2d58d26b0 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll index bd51f29d854e..0b81e0e53fb7 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll index 4809ef738022..a563e4e4d510 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript private import semmle.javascript.frameworks.ConnectExpressShared diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll index 09695a76f10b..267e97a24ab4 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript private import SyntacticHeuristics diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll index a823fa428f90..a7d0a720ca30 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript import SyntacticHeuristics diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll index 48ca553da1b2..681e2450cae4 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll b/javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll index ae26e66b3b4f..bcb809f4b066 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll @@ -1,6 +1,8 @@ /** * Provides heuristically recognized sinks for security queries. */ +overlay[local?] +module; import javascript private import SyntacticHeuristics diff --git a/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll b/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll index 12356d1bf42b..1a9dd67b7543 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll @@ -3,6 +3,8 @@ * * INTERNAL: Do not use outside of the `semmle.javascript.heuristics` module. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/all.qll b/javascript/ql/lib/semmle/javascript/heuristics/all.qll index 8bb54883b969..c8c36700b4fd 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/all.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/all.qll @@ -5,6 +5,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import AdditionalFrameworks import AdditionalPromises diff --git a/javascript/ql/lib/semmle/javascript/internal/BindingInfo.qll b/javascript/ql/lib/semmle/javascript/internal/BindingInfo.qll index f5f8bfb2d1ef..7c36aa9c0989 100644 --- a/javascript/ql/lib/semmle/javascript/internal/BindingInfo.qll +++ b/javascript/ql/lib/semmle/javascript/internal/BindingInfo.qll @@ -1,6 +1,8 @@ /** * Provides a limited public interface to name/type resolution information. */ +overlay[local?] +module; private import javascript private import semmle.javascript.internal.NameResolution diff --git a/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll b/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll index 43ae4ffd43e6..adb09ffc599a 100644 --- a/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll +++ b/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll @@ -1,6 +1,8 @@ /** * Provides name resolution and propagates type information. */ +overlay[local?] +module; private import javascript @@ -401,6 +403,7 @@ module NameResolution { /** * Holds if data should propagate from `node1` to `node2`. */ + overlay[caller?] pragma[inline] predicate step(Node node1, Node node2) { commonStep(node1, node2) diff --git a/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll b/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll index 73885f833051..181f673bc25e 100644 --- a/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll +++ b/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.internal.NameResolution::NameResolution private import semmle.javascript.internal.UnderlyingTypes diff --git a/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll b/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll index 5461cb3d50f2..a657f6d9f8d5 100644 --- a/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll +++ b/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll @@ -1,6 +1,8 @@ /** * Provides name resolution and propagates type information. */ +overlay[local?] +module; private import javascript private import semmle.javascript.internal.NameResolution::NameResolution diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AllFlowSummaries.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AllFlowSummaries.qll index dfbe9ef7da31..79657d030a8a 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AllFlowSummaries.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AllFlowSummaries.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import AmbiguousCoreMethods private import Arrays private import AsyncAwait diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll b/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll index dc90dcc39469..d926e118ae64 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll @@ -2,6 +2,8 @@ * Provides predicates for use in `Folder::ResolveSig` in order to resolve * paths using JavaScript semantics. */ +overlay[local?] +module; private import javascript private import semmle.javascript.TSConfig diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll index 5f4a6eb930ea..4bbf3b6f62b6 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.internal.paths.JSPaths diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll index ad5552ce78c3..bc29ab168478 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript /** diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll index 63ffd9554773..65666d7f7f4d 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.internal.paths.PackageJsonEx private import semmle.javascript.internal.paths.JSPaths diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll index d3da0a51cfa3..12f1ecf01fd6 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll @@ -1,6 +1,8 @@ /** * Provides an extensible mechanism for modeling path mappings. */ +overlay[local?] +module; private import javascript private import semmle.javascript.TSConfig diff --git a/javascript/ql/lib/semmle/javascript/linters/ESLint.qll b/javascript/ql/lib/semmle/javascript/linters/ESLint.qll index acc52a5d6b51..96a5fd22cf73 100644 --- a/javascript/ql/lib/semmle/javascript/linters/ESLint.qll +++ b/javascript/ql/lib/semmle/javascript/linters/ESLint.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with ESLint directives and configurations. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/linters/JSLint.qll b/javascript/ql/lib/semmle/javascript/linters/JSLint.qll index d03ecb2abf9b..108010db5631 100644 --- a/javascript/ql/lib/semmle/javascript/linters/JSLint.qll +++ b/javascript/ql/lib/semmle/javascript/linters/JSLint.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSLint/JSHint directives. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/linters/Linting.qll b/javascript/ql/lib/semmle/javascript/linters/Linting.qll index 887467010457..f86dae076fb8 100644 --- a/javascript/ql/lib/semmle/javascript/linters/Linting.qll +++ b/javascript/ql/lib/semmle/javascript/linters/Linting.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with various JavaScript linters. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll b/javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll index 0bc4f32d4bc1..ba674b836c7e 100644 --- a/javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll +++ b/javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript /** diff --git a/javascript/ql/lib/semmle/javascript/security/CommonFlowState.qll b/javascript/ql/lib/semmle/javascript/security/CommonFlowState.qll index 52e1e0d00f38..8227cfef6f4d 100644 --- a/javascript/ql/lib/semmle/javascript/security/CommonFlowState.qll +++ b/javascript/ql/lib/semmle/javascript/security/CommonFlowState.qll @@ -1,6 +1,8 @@ /** * Contains a class with flow states that are used by multiple queries. */ +overlay[local?] +module; private import javascript private import TaintedUrlSuffixCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll index aed0e26a6b3f..9fcf5d380a12 100644 --- a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll @@ -3,6 +3,8 @@ * overly permissive CORS configurations, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll index 03d20578b0e1..8f0fd1152292 100644 --- a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll @@ -7,6 +7,8 @@ * otherwise `CorsPermissiveConfigurationCustomizations` should * be imported instead. */ +overlay[local?] +module; import javascript import CorsPermissiveConfigurationCustomizations::CorsPermissiveConfiguration diff --git a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll index 13a03a3bd888..cdd2414f15a5 100644 --- a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll +++ b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll @@ -1,5 +1,7 @@ /** * Provides classes modeling cryptographic algorithms, separated into strong and weak variants. */ +overlay[local?] +module; import codeql.concepts.CryptoAlgorithms diff --git a/javascript/ql/lib/semmle/javascript/security/FunctionalityFromUntrustedSource.qll b/javascript/ql/lib/semmle/javascript/security/FunctionalityFromUntrustedSource.qll index f837c710fd46..661996223e12 100644 --- a/javascript/ql/lib/semmle/javascript/security/FunctionalityFromUntrustedSource.qll +++ b/javascript/ql/lib/semmle/javascript/security/FunctionalityFromUntrustedSource.qll @@ -1,6 +1,8 @@ /** * Provides classes for finding functionality that is loaded from untrusted sources and used in script or frame elements. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll b/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll index 13d5033458af..87fe5d164cdd 100644 --- a/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll +++ b/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with incomplete blacklist sanitizers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll b/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll index 2a2d4d4d6014..2b275421cc17 100644 --- a/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll @@ -1,6 +1,8 @@ /** * Provides shared predicates for reasoning about improper multi-character sanitization. */ +overlay[local?] +module; import IncompleteMultiCharacterSanitizationSpecific diff --git a/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationSpecific.qll b/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationSpecific.qll index 10d9ab19f983..b21074fa990e 100644 --- a/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationSpecific.qll @@ -1,6 +1,8 @@ /** * Provides language-specific predicates for reasoning about improper multi-character sanitization. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.regexp.RegExpTreeView::RegExpTreeView as TreeView diff --git a/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll b/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll index 183fca296c76..e89e2850871d 100644 --- a/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll @@ -1,4 +1,6 @@ /** Classses and predicates for reasoning about passwords in configuration files. */ +overlay[local?] +module; import javascript import semmle.javascript.RestrictedLocations diff --git a/javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll b/javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll index 05a6fbc17d46..c6bd19c10b84 100644 --- a/javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll +++ b/javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll @@ -8,6 +8,8 @@ * In addition, there are methods that ought not to be executed or not in a fashion that the user * can control. This includes authorization methods such as logins, and sending of data, etc. */ +overlay[local?] +module; import javascript import codeql.concepts.internal.SensitiveDataHeuristics diff --git a/javascript/ql/lib/semmle/javascript/security/TaintedObject.qll b/javascript/ql/lib/semmle/javascript/security/TaintedObject.qll index a300291ae9cd..9521550d9b9e 100644 --- a/javascript/ql/lib/semmle/javascript/security/TaintedObject.qll +++ b/javascript/ql/lib/semmle/javascript/security/TaintedObject.qll @@ -12,6 +12,8 @@ * 3. The flow steps from `TaintedObject::isAdditionalFlowStep`. * 4. The barriers from `TaintedObject::SanitizerGuard::getABarrierNode(state)`. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll index 5dc687deecae..509622b80276 100644 --- a/javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll @@ -2,6 +2,8 @@ * Provides access to the "tainted object" flow label defined in `TaintedObject.qll`, without * materializing that flow label. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll index 1d4ff0c4b7fe..de256d95296f 100644 --- a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll +++ b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll @@ -2,6 +2,8 @@ * Provides a flow label for reasoning about URLs with a tainted query and fragment part, * which we collectively refer to as the "suffix" of the URL. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffixCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffixCustomizations.qll index 841f830f2bf9..7b6ea30c0e32 100644 --- a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffixCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffixCustomizations.qll @@ -2,6 +2,8 @@ * Provides a flow state for reasoning about URLs with a tainted query and fragment part, * which we collectively refer to as the "suffix" of the URL. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.DataFlowPrivate as DataFlowPrivate diff --git a/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll b/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll index e66200370dd6..b413ecd253db 100644 --- a/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll +++ b/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll @@ -1,6 +1,8 @@ /** * Provides predicates and classes for working with useless uses of the unix command `cat`. */ +overlay[local?] +module; import javascript import Expressions.ExprHasNoEffect diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll index e0db75ab52c0..93310a41ff66 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll @@ -3,6 +3,8 @@ * sensitive information in broken or weak cryptographic algorithms, * as well as extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll index 70641af0286a..03ad511b1eee 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sinks for reasoning about storage of sensitive information * in build artifact, as well as extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll index a7bbc73ce038..0924beccf8ac 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll @@ -3,6 +3,8 @@ * clear-text logging of sensitive information, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll index 1d57fdb50fd0..53e9eeb870f4 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll @@ -3,6 +3,8 @@ * cleartext storage of sensitive information, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll index 1b987ea2679e..4ada245d1aec 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll @@ -3,6 +3,8 @@ * unvalidated URL redirection problems on the client side, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.TaintedUrlSuffixCustomizations @@ -63,6 +65,7 @@ module ClientSideUrlRedirect { /** * Holds if `node` extracts a part of a URL that does not contain the suffix. */ + overlay[caller?] pragma[inline] deprecated predicate isPrefixExtraction(DataFlow::MethodCallNode node) { // Block flow through prefix-extraction `substring(0, ...)` and `split("#")[0]` diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll index 526eaf1be361..ac7c9b89b450 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll @@ -6,6 +6,8 @@ * `ClientSideUrlRedirect::Configuration` is needed, otherwise * `ClientSideUrlRedirectCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import UrlConcatenation diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll index 8fded55bc896..e1c38ad3c4c2 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll @@ -3,6 +3,8 @@ * code injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll index 9762c1142b99..449aa17cb51a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll @@ -3,6 +3,8 @@ * command-injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll index 034699cee0d5..18b32f90aeb9 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll @@ -3,6 +3,8 @@ * bypass of sensitive action guards, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll index eaf78fd4c4c9..b615cef87254 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll @@ -3,6 +3,8 @@ * CORS misconfiguration for credentials transfer, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll index f959de6c0b5e..7ead4652939e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll @@ -1,6 +1,8 @@ /** * Provides predicates for reasoning about DOM types and methods. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll index eaac474b2074..58f1229355df 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll @@ -2,6 +2,8 @@ * Provides sources, sinks and sanitizers for reasoning about * DoS attacks due to inefficient handling of user-controlled objects. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.TaintedObjectCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll index ad03ad93b949..83f3ac652c8d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll @@ -2,6 +2,8 @@ * Provides a taint tracking configuration for reasoning about DoS attacks * due to inefficient handling of user-controlled objects. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll index 5be7082137a9..6ac787b078ab 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll @@ -3,6 +3,8 @@ * comparisons that relies on different kinds of HTTP request data, as * well as extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll index 1440fb5539d7..571b3456c051 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources for reasoning about DOM-based * cross-site scripting vulnerabilities. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll index 36d5b3ba0a6b..5bb0614147b6 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll @@ -2,6 +2,8 @@ * Provides a taint-tracking configuration for reasoning about DOM-based * cross-site scripting vulnerabilities. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.TaintedUrlSuffix diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll index 70281110a5fb..cf556d06e3eb 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll @@ -3,6 +3,8 @@ * cross-site scripting vulnerabilities where the taint-flow passes through a thrown * exception. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll index d7f4fe954f9c..4d2de67fe7d0 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll @@ -3,6 +3,8 @@ * scripting vulnerabilities where the taint-flow passes through a thrown * exception. */ +overlay[local?] +module; import javascript import DomBasedXssCustomizations::DomBasedXss as DomBasedXssCustom diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll index f59c7b78e367..e97f65e02318 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll @@ -2,6 +2,8 @@ * Provides sources, sinks and sanitizers for reasoning about flow of * untrusted data into an external API. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll index 8fac31ddf54d..d94c1bac78a2 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll @@ -3,6 +3,8 @@ * file data in outbound network requests, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll index 8bd9b290fc6b..303a6995af7c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll @@ -3,6 +3,8 @@ * hardcoded credentials, as well as extension points for adding your * own. */ +overlay[local?] +module; import semmle.javascript.filters.ClassifyFiles import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll index 9ec6f2d5b4ad..42f4ec66b5cf 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll @@ -3,6 +3,8 @@ * hard-coded data being interpreted as code, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.dataflow.CodeInjectionCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll index 0d33ee11876f..925fff311f01 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll @@ -7,6 +7,8 @@ * otherwise `HardcodedDataInterpretedAsCodeCustomizations` should be * imported instead. */ +overlay[local?] +module; import javascript import HardcodedDataInterpretedAsCodeCustomizations::HardcodedDataInterpretedAsCode diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll index 46823c990ef7..6494e553093c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll @@ -3,6 +3,8 @@ * writing user-controlled data to files, as well as extension points * for adding your own. */ +overlay[local?] +module; /** * Provides default sources, sinks and sanitizers for reasoning about diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessSpecific.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessSpecific.qll index 2b44de07a4c3..c35682bc3e35 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessSpecific.qll @@ -1,6 +1,8 @@ /** * Provides imports and classes needed for `HttpToFileAccessQuery` and `HttpToFileAccessCustomizations`. */ +overlay[local?] +module; import javascript private import HttpToFileAccessCustomizations::HttpToFileAccess diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll index 4bf212b90d2a..493fd2b8e7de 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll @@ -3,6 +3,8 @@ * improper code sanitization, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll index f421a92298f9..864447d6ffca 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll @@ -3,6 +3,8 @@ * incomplete HTML sanitization vulnerabilities, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.IncompleteBlacklistSanitizer diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll index 578c15635bbb..979d610ccc5e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll @@ -6,6 +6,8 @@ * `IncompleteHtmlAttributeSanitization::Configuration` is needed, otherwise * `IncompleteHtmlAttributeSanitizationCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import IncompleteHtmlAttributeSanitizationCustomizations::IncompleteHtmlAttributeSanitization diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll index 6d6c9c3d75fa..fc4bfd3d0eed 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll @@ -1,6 +1,8 @@ /** * Provides predicates for reasoning about indirect command arguments. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 84c4600fbc03..3a6418c3aa9f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -3,6 +3,8 @@ * command-injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll index c7acce602b72..ffe1ae2c19e4 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll @@ -3,6 +3,8 @@ * download of sensitive file through insecure connection, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll index ffcfead78961..07d11e282ff1 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll @@ -5,6 +5,8 @@ * `InsecureDownload::Configuration` is needed, otherwise * `InsecureDownloadCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import InsecureDownloadCustomizations::InsecureDownload diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll index d40e3a510c76..731cd55ed55c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll @@ -3,6 +3,8 @@ * random values that are not cryptographically secure, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureTemporaryFileCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureTemporaryFileCustomizations.qll index 216482947aba..270158216dbb 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureTemporaryFileCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureTemporaryFileCustomizations.qll @@ -3,6 +3,8 @@ * insecure temporary file creation, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll index 8901be9962f8..830fe27b8860 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll @@ -3,6 +3,8 @@ * password hashing with insufficient computational effort, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll index 63da6fca1054..9e6454fabdf8 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll @@ -3,6 +3,8 @@ * DoS attacks using objects with unbounded length property, * as well as extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll index 522df62eca56..f0b7090d8436 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll @@ -6,6 +6,8 @@ * `LoopBoundInjection::Configuration` is needed, otherwise * `LoopBoundInjectionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import LoopBoundInjectionCustomizations::LoopBoundInjection diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll index 5f4ad1b3d73e..9a914c1ab296 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll @@ -21,6 +21,8 @@ * For `RateLimitedRouteHandlerExpr`, the default subclasses model popular npm packages; * other means of rate-limiting can be supported by adding more subclasses. */ +overlay[local?] +module; import javascript private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpressShared diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll index 36c0601d501c..901087cb422f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll @@ -3,6 +3,8 @@ * NoSQL injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll index e7d93aabb977..1316762e64b7 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll @@ -6,6 +6,8 @@ * `NosqlInjection::Configuration` is needed, otherwise * `NosqlInjectionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll index 62f87e29b0b9..df71e655b9db 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll @@ -3,6 +3,8 @@ * cross-window communication with unrestricted origin, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions::HeuristicNames diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll index 81770b95a02e..285c840c3856 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll @@ -2,6 +2,8 @@ * Provides predicates for reasoning about flow of user-controlled values that are used * as property names. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll index bb2f9739501c..6be49fbd671f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll @@ -2,6 +2,8 @@ * Provides sources, sinks, and sanitizers for reasoning about assignments * that my cause prototype pollution. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll index 96eed4cadc2b..e0a9e5844402 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll @@ -6,6 +6,8 @@ * `PrototypePollutingAssignment::Configuration` is needed, otherwise * `PrototypePollutingAssignmentCustomizations` should be imported instead. */ +overlay[local?] +module; private import javascript private import semmle.javascript.DynamicPropertyAccess diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll index 1e95e4b550fb..4c429c4c0cb7 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll @@ -3,6 +3,8 @@ * user-controlled objects flowing into a vulnerable `extends` call, * as well as extension points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll index 86fbb1273d97..d39aa9ec4e55 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll @@ -6,6 +6,8 @@ * `PrototypePollution::Configuration` is needed, otherwise * `PrototypePollutionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll index 70b2685d90d4..14f8f7fef4b6 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources for reasoning about reflected * cross-site scripting vulnerabilities. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll index 5ee39219d260..5a972629ef91 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll @@ -3,6 +3,8 @@ * untrusted user input used to construct regular expressions, as well * as extension points for adding your own. */ +overlay[local?] +module; import javascript private import codeql.threatmodels.ThreatModels diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll index 6157671e6a91..a1c5ee26631c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll @@ -4,6 +4,8 @@ * property, into a header or for calling an object's method, as well * as extension points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Express diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll index ec46ef91c3c0..dda51bcca412 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources, sinks and sanitizers for reasoning about * request forgery, as well as extension points for adding your own. */ +overlay[local?] +module; import semmle.javascript.security.dataflow.RemoteFlowSources diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll index e24de9f4d6f9..da333d36b2af 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll @@ -3,6 +3,8 @@ * resource exhaustion vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll index 416ad56bef16..5e0c98d016cd 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll @@ -3,6 +3,8 @@ * second order command injection, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.PackageExports as Exports diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionQuery.qll index 0c5af5abd37c..5d6a35ce4602 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionQuery.qll @@ -6,6 +6,8 @@ * `SecondOrderCommandInjection::Configuration` is needed, otherwise * `SecondOrderCommandInjectionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import SecondOrderCommandInjectionCustomizations::SecondOrderCommandInjection diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll index 55815717e98c..22e377d59164 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll @@ -3,6 +3,8 @@ * unvalidated URL redirection problems on the server side, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript import RemoteFlowSources diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll index 87d7d340afd1..5d732bd3921e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll @@ -3,6 +3,8 @@ * command-injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.TaintedPathCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll index 8afb65519ad4..7c140061758f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll @@ -3,6 +3,8 @@ * string based query injection vulnerabilities, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll index 205c00f8f795..4ea1570012fc 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll @@ -3,6 +3,8 @@ * stack trace exposure vulnerabilities, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssCustomizations.qll index 412332b54115..5b213d590e8e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources, sinks and sanitizers for reasoning about * stored cross-site scripting vulnerabilities. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll index ec94277235cd..28b7c6534abc 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources, sinks and sanitizers for reasoning about * format injections, as well as extension points for adding your own. */ +overlay[local?] +module; /** * Provides default sources, sinks and sanitizers for reasoning about diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringSpecific.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringSpecific.qll index e2a28a68baf7..69b4488ef816 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringSpecific.qll @@ -1,6 +1,8 @@ /** * Provides JS-specific imports needed for `TaintedFormatStringQuery` and `TaintedFormatStringCustomizations`. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.DOM diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll index f863b86a3b57..acd101f871c8 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll @@ -3,6 +3,8 @@ * tainted-path vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll index 8b50a69cedce..89a32bb0e434 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll @@ -6,6 +6,8 @@ * `TaintedPath::Configuration` is needed, otherwise * `TaintedPathCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript private import TaintedPathCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll index b141feb1409f..e1d1051eb40d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll @@ -3,6 +3,8 @@ * template object injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.TaintedObjectCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll index 348e59937b5e..667d59526747 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll @@ -6,6 +6,8 @@ * `TemplateObjectInjection::Configuration` is needed, otherwise * `TemplateObjectInjectionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import TemplateObjectInjectionCustomizations::TemplateObjectInjection diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll index de09aedce124..415de1671cb5 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll @@ -3,6 +3,8 @@ * type confusion for HTTP request inputs, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstruction.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstruction.qll index e29d5d87a70f..365c61fe96f6 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstruction.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstruction.qll @@ -6,6 +6,8 @@ * `UnsafeCodeConstruction::Configuration` is needed, otherwise * `UnsafeCodeConstructionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstructionCustomizations.qll index 95454df7743f..6ec98bd918a7 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstructionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstructionCustomizations.qll @@ -3,6 +3,8 @@ * constructed from library input vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll index 2e13e0ee7f9b..3e54a28fd54b 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll @@ -3,6 +3,8 @@ * unsafe deserialization, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll index 756efb5f3fb6..5afc78aa0ad9 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll @@ -4,6 +4,8 @@ * with unsafe methods, as well as extension points for adding your * own. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Express diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll index 423b50f17f70..4f2915998dd3 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll @@ -6,6 +6,8 @@ * `UnsafeDynamicMethodAccess::Configuration` is needed, otherwise * `UnsafeDynamicMethodAccessCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import PropertyInjectionShared diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll index 06bad34b80c4..195b097b5f9d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll @@ -3,6 +3,8 @@ * unsafe HTML constructed from library input, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll index 913329813c1b..be797637b364 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll @@ -2,6 +2,8 @@ * Provides a taint-tracking configuration for reasoning about * unsafe HTML constructed from library input vulnerabilities. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.dataflow.DomBasedXssCustomizations::DomBasedXss as DomBasedXss diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll index 3fb2827707e3..fe5e15353ab9 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll @@ -3,6 +3,8 @@ * unsafe jQuery plugins, as well as extension points for adding your * own. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index e65fac9530d7..de19940625ba 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -3,6 +3,8 @@ * shell command constructed from library input vulnerabilities, * as well as extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.PackageExports as Exports diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll index e516167a30b4..7fedd47a566a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll @@ -3,6 +3,8 @@ * unvalidated dynamic method calls, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Express diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll index 7b6a6124edaf..e0316f20a32d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll @@ -7,6 +7,8 @@ * `UnvalidatedDynamicMethodCallCustomizations` should be imported * instead. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Express diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll index 81b7be46cb26..0e79dbb73efb 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll @@ -3,6 +3,8 @@ * the characters `?` and `#`, which are considered sanitizers for * the URL redirection queries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll index 15ba3e2a17d2..b2e86624851a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll @@ -3,6 +3,8 @@ * XML-bomb vulnerabilities, as well as extension points for adding * your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.DOM diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll index 6eb3f12d16ad..dc47c919339c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll @@ -3,6 +3,8 @@ * untrusted user input used in XPath expression, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.DOM diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll index f139ccc48dbb..123cb3fb2513 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates used by the XSS queries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll index 865324ed8d5b..3e443266caaa 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources for reasoning about * cross-site scripting vulnerabilities through the DOM. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll index 9f6fe305bdf9..5a6454d6775a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll @@ -3,6 +3,8 @@ * XML External Entity (XXE) vulnerabilities, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.DOM diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll index 01e40fd5dbf5..91443624f464 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll @@ -3,6 +3,8 @@ * unsafe zip and tar archive extraction, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll index b59a78462b8c..3a235e9ac0eb 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll @@ -6,6 +6,8 @@ * `ZipSlip::Configuration` is needed, otherwise * `ZipSlipCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import ZipSlipCustomizations::ZipSlip diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/HostnameRegexp.qll b/javascript/ql/lib/semmle/javascript/security/regexp/HostnameRegexp.qll index c9853ce35f18..6c63fbbcb67b 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/HostnameRegexp.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/HostnameRegexp.qll @@ -2,6 +2,8 @@ * Provides predicates for reasoning about regular expressions * that match URLs and hostname patterns. */ +overlay[local?] +module; private import javascript as JS private import semmle.javascript.security.regexp.RegExpTreeView::RegExpTreeView as TreeImpl diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/PolynomialReDoSCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/regexp/PolynomialReDoSCustomizations.qll index dce63894f8b4..6e6877ce8168 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/PolynomialReDoSCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/PolynomialReDoSCustomizations.qll @@ -3,6 +3,8 @@ * polynomial regular expression denial-of-service attacks, as well * as extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.regexp.RegExpTreeView::RegExpTreeView as TreeView diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll b/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll index e5aa0e490fa9..d0032e0489c4 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll @@ -1,6 +1,8 @@ /** * Provides JavaScript-specific definitions for use in the NfaUtils module. */ +overlay[local?] +module; private import codeql.regex.nfa.NfaUtils as NfaUtils private import codeql.regex.RegexTreeView diff --git a/javascript/ql/lib/utils/test/ConsistencyChecking.qll b/javascript/ql/lib/utils/test/ConsistencyChecking.qll index f614a93500d7..8b87537db083 100644 --- a/javascript/ql/lib/utils/test/ConsistencyChecking.qll +++ b/javascript/ql/lib/utils/test/ConsistencyChecking.qll @@ -3,6 +3,8 @@ * * Will be replaced with standardized inline test expectations in the future. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/utils/test/InlineFlowTestUtil.qll b/javascript/ql/lib/utils/test/InlineFlowTestUtil.qll index 4072e4dd9e6b..11e81f40ed15 100644 --- a/javascript/ql/lib/utils/test/InlineFlowTestUtil.qll +++ b/javascript/ql/lib/utils/test/InlineFlowTestUtil.qll @@ -4,6 +4,8 @@ * We reuse these predicates in some type-tracking tests that don't wish to bring in the * test configuration from `InlineFlowTest`. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/utils/test/InlineSummaries.qll b/javascript/ql/lib/utils/test/InlineSummaries.qll index 0366736eaf66..87f58f91f65d 100644 --- a/javascript/ql/lib/utils/test/InlineSummaries.qll +++ b/javascript/ql/lib/utils/test/InlineSummaries.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/utils/test/LegacyDataFlowDiff.qll b/javascript/ql/lib/utils/test/LegacyDataFlowDiff.qll index 0995d06199c2..457da8000c53 100644 --- a/javascript/ql/lib/utils/test/LegacyDataFlowDiff.qll +++ b/javascript/ql/lib/utils/test/LegacyDataFlowDiff.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private signature class LegacyConfigSig { diff --git a/javascript/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll b/javascript/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll index 42eb94230ae6..feea08bf9f8f 100644 --- a/javascript/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll +++ b/javascript/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript as JS private import codeql.util.test.InlineExpectationsTest From c8e83df43d063ffe38ef91e07d60b79e02275f55 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 10 Oct 2025 21:37:01 +0200 Subject: [PATCH 56/59] JS: Add overlay[global] to abstract classes with fields Some abstract classes defines fields without binding them, leaving it up to the subclasses to bind them. When combined with overlay[local?], the charpred for such an abstract class can become local, while the subclasses are global. The means the charpred needs to be materialized, even though it doesn't bind the fields, leading to a cartesian product. --- javascript/ql/lib/semmle/javascript/DOM.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll | 2 ++ javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll | 1 + javascript/ql/lib/semmle/javascript/frameworks/SQL.qll | 1 + .../dataflow/SecondOrderCommandInjectionCustomizations.qll | 1 + .../javascript/security/dataflow/TaintedPathCustomizations.qll | 1 + .../security/dataflow/UnsafeHtmlConstructionCustomizations.qll | 1 + 7 files changed, 8 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/DOM.qll b/javascript/ql/lib/semmle/javascript/DOM.qll index 71f34904b081..87e5f66f87f4 100644 --- a/javascript/ql/lib/semmle/javascript/DOM.qll +++ b/javascript/ql/lib/semmle/javascript/DOM.qll @@ -194,6 +194,7 @@ module DOM { * A data flow node or other program element that may refer to * a DOM element. */ + overlay[global] abstract class Element extends Locatable { ElementDefinition defn; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll b/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll index 8b08275dc53a..f4af2e9b34f3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll @@ -97,6 +97,7 @@ module EventRegistration { /** * A registration of an event handler on an EventEmitter. */ + overlay[global] abstract class Range extends DataFlow::Node { EventEmitter::Range emitter; @@ -151,6 +152,7 @@ module EventDispatch { /** * A dispatch of an event on an EventEmitter. */ + overlay[global] abstract class Range extends DataFlow::Node { EventEmitter::Range emitter; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll index 89d436bb64c7..5ea54cbb8c0f 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll @@ -260,6 +260,7 @@ module NodeJSLib { DataFlow::Node getRouteHandlerNode() { result = handler } } + overlay[global] abstract private class HeaderDefinition extends Http::Servers::StandardHeaderDefinition { ResponseNode r; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll index eac5618ea604..58ab4e60c46c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll @@ -18,6 +18,7 @@ module SQL { * An dataflow node that sanitizes a string to make it safe to embed into * a SQL command. */ + overlay[global] abstract class SqlSanitizer extends DataFlow::Node { DataFlow::Node input; DataFlow::Node output; diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll index 5e0c98d016cd..c9e8eef77b53 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll @@ -131,6 +131,7 @@ module SecondOrderCommandInjection { /** * A sink that invokes a command described by the `VulnerableCommand` class. */ + overlay[global] abstract class VulnerableCommandSink extends Sink { VulnerableCommand cmd; diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll index acd101f871c8..70eb1a56fbab 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll @@ -196,6 +196,7 @@ module TaintedPath { * There are currently four flow labels, representing the different combinations of * normalization and absoluteness. */ + overlay[global] abstract class PosixPath extends DataFlow::FlowLabel { Normalization normalization; Relativeness relativeness; diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll index 195b097b5f9d..b3641e9ba0d4 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll @@ -103,6 +103,7 @@ module UnsafeHtmlConstruction { * A sink for `js/html-constructed-from-input` that constructs some HTML where * that HTML is later used in `xssSink`. */ + overlay[global] abstract class XssSink extends Sink { DomBasedXss::Sink xssSink; From e0fb2d07f0f1127263967a6836fc1eabc002de96 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Oct 2025 10:14:23 +0100 Subject: [PATCH 57/59] JS: Use forceLocal to implement MkTypeUse --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index a0927f850cb7..03edc3a3bb9d 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -735,6 +735,14 @@ module API { */ cached private module Impl { + private predicate hasTypeUse(string moduleName, string exportName) { + any(TypeAnnotation n).hasUnderlyingType(moduleName, exportName) + } + + overlay[local] + private predicate hasTypeUseLocal(string moduleName, string exportName) = + forceLocal(hasTypeUse/2)(moduleName, exportName) + overlay[local] cached newtype TApiNode = @@ -771,10 +779,7 @@ module API { } or MkUse(DataFlow::Node nd) { nd instanceof DataFlow::SourceNode } or /** A use of a TypeScript type. */ - MkTypeUse(string moduleName, string exportName) { - // any(TypeAnnotation n).hasUnderlyingType(moduleName, exportName) - none() // TODO - } or + MkTypeUse(string moduleName, string exportName) { hasTypeUseLocal(moduleName, exportName) } or MkSyntheticCallbackArg(DataFlow::InvokeNode nd) class TDef = MkModuleDef or TNonModuleDef; From a2251ecd6dd14cd887392b8e01d38cde32fa2338 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Oct 2025 10:32:57 +0100 Subject: [PATCH 58/59] JS: Add a few missing node types --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 03edc3a3bb9d..ae79d7938243 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -763,10 +763,16 @@ module API { or nd = any(DataFlow::FunctionNode fn).getAReturn() or + nd = any(DataFlow::FunctionNode fn).getExceptionalReturn() + or nd = any(DataFlow::InvokeNode i).getAnArgument() or nd = any(DataFlow::InvokeNode i).getASpreadArgument() or + nd = any(DataFlow::InvokeNode i).getExceptionalReturn() + or + nd = any(ThrowStmt stmt).getExpr().flow() + or nd = any(DataFlow::CallNode c).getReceiver() or nd = DataFlow::valueNode(any(ExportNamedDeclaration decl).getOperand()) @@ -776,6 +782,8 @@ module API { nd = any(ExportNamedDeclaration decl).getOperand().(DeclStmt).getADecl().getInit().flow() or nd = any(ExportNamespaceSpecifier spec | exists(spec.getExportedName())).flow() + or + nd = any(MemberDeclaration m).getInit().flow() } or MkUse(DataFlow::Node nd) { nd instanceof DataFlow::SourceNode } or /** A use of a TypeScript type. */ From c8abbdc45fad358dfaa31103ce085770c2de3f0c Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 3 Nov 2025 11:52:06 +0100 Subject: [PATCH 59/59] JS: Remove global dependency that wasnt needed anyway --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 -- 1 file changed, 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index ae79d7938243..d1cd1cb33de5 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -1927,8 +1927,6 @@ module API { or name = any(DataFlow::PropRef pr).getPropertyName() or - AccessPath::isAssignedInUniqueFile(name) - or exists(AccessPath::getAnAssignmentTo(_, name)) or name = DataFlow::PseudoProperties::arrayLikeElement()