diff --git a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll index c098c60816e..e164adf786f 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll @@ -24,6 +24,7 @@ private import internal.FlowSteps as FlowSteps private import internal.DataFlowNode private import internal.AnalyzedParameters private import internal.PreCallGraphStep +private import internal.ModuleInterop private import semmle.javascript.internal.CachedStages module DataFlow { diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/ModuleInterop.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/ModuleInterop.qll new file mode 100644 index 00000000000..47a26350f97 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/ModuleInterop.qll @@ -0,0 +1,46 @@ +private import javascript +private import PreCallGraphStep as PCG + +class ES2015InteropCall extends DataFlow::CallNode { + ES2015InteropCall() { + this.getCalleeName() = ["_interopRequireDefault", "_interopRequireWildcard"] + } + + private Import getAnImport() { + this.getArgument(0).getALocalSource() = result.getImportedModuleNode() + } + + Module getImportedModule() { result = this.getAnImport().getImportedModule() } + + predicate isImportingESModule() { + this.getImportedModule() instanceof ES2015Module + or + exists(this.getImportedModule().getAnExportedValue("__esModule")) + } + + DataFlow::SourceNode getImportedObject() { + this.isImportingESModule() and + result = this + or + (not this.isImportingESModule() or this.getCalleeName() = "_interopRequireWildcard") and + result = this.getAPropertyRead("default") + } +} + +predicate interopModuleStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(ES2015InteropCall call | + pred = call.getArgument(0) and + succ = call.getImportedObject() + or + exists(string prop | + pred = call.getImportedModule().getAnExportedValue(prop) and + succ = call.getImportedObject().getAPropertyRead(prop) + ) + ) +} + +private class Step extends PCG::PreCallGraphStep { + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + interopModuleStep(pred, succ) + } +}