Merge pull request #6261 from max-schaefer/js/module-constructor

Approved by asgerf
This commit is contained in:
CodeQL CI
2021-07-16 00:28:30 -07:00
committed by GitHub
6 changed files with 72 additions and 52 deletions

View File

@@ -617,11 +617,11 @@ module API {
cached
predicate use(TApiNode nd, DataFlow::Node ref) {
exists(string m, Module mod | nd = MkModuleDef(m) and mod = importableModule(m) |
ref.(ModuleVarNode).getModule() = mod
ref = DataFlow::moduleVarNode(mod)
)
or
exists(string m, Module mod | nd = MkModuleExport(m) and mod = importableModule(m) |
ref.(ExportsVarNode).getModule() = mod
ref = DataFlow::exportsVarNode(mod)
or
exists(DataFlow::Node base | use(MkModuleDef(m), base) |
ref = trackUseNode(base).getAPropertyRead("exports")
@@ -742,12 +742,9 @@ module API {
or
// additional backwards step from `require('m')` to `exports` or `module.exports` in m
exists(Import imp | imp.getImportedModuleNode() = trackDefNode(nd, t.continue()) |
result.(ExportsVarNode).getModule() = imp.getImportedModule()
result = DataFlow::exportsVarNode(imp.getImportedModule())
or
exists(ModuleVarNode mod |
mod.getModule() = imp.getImportedModule() and
result = mod.(DataFlow::SourceNode).getAPropertyRead("exports")
)
result = DataFlow::moduleVarNode(imp.getImportedModule()).getAPropertyRead("exports")
)
or
t = defStep(nd, result)
@@ -981,46 +978,3 @@ private module Label {
/** Gets the `promisedError` edge label connecting a promise to its rejected value. */
string promisedError() { result = "promisedError" }
}
private class NodeModuleSourcesNodes extends DataFlow::SourceNode::Range {
Variable v;
NodeModuleSourcesNodes() {
exists(NodeModule m |
this = DataFlow::ssaDefinitionNode(SSA::implicitInit(v)) and
v = [m.getModuleVariable(), m.getExportsVariable()]
)
}
Variable getVariable() { result = v }
}
/**
* A CommonJS/AMD `module` variable.
*/
private class ModuleVarNode extends DataFlow::Node {
Module m;
ModuleVarNode() {
this.(NodeModuleSourcesNodes).getVariable() = m.(NodeModule).getModuleVariable()
or
DataFlow::parameterNode(this, m.(AmdModule).getDefine().getModuleParameter())
}
Module getModule() { result = m }
}
/**
* A CommonJS/AMD `exports` variable.
*/
private class ExportsVarNode extends DataFlow::Node {
Module m;
ExportsVarNode() {
this.(NodeModuleSourcesNodes).getVariable() = m.(NodeModule).getExportsVariable()
or
DataFlow::parameterNode(this, m.(AmdModule).getDefine().getExportsParameter())
}
Module getModule() { result = m }
}

View File

@@ -347,6 +347,55 @@ module SourceNode {
}
}
private class NodeModuleSourcesNodes extends SourceNode::Range {
Variable v;
NodeModuleSourcesNodes() {
exists(NodeModule m |
this = DataFlow::ssaDefinitionNode(SSA::implicitInit(v)) and
v = [m.getModuleVariable(), m.getExportsVariable()]
)
}
Variable getVariable() { result = v }
}
/**
* A CommonJS/AMD `module` variable.
*/
private class ModuleVarNode extends DataFlow::Node {
Module m;
ModuleVarNode() {
this.(NodeModuleSourcesNodes).getVariable() = m.(NodeModule).getModuleVariable()
or
DataFlow::parameterNode(this, m.(AmdModule).getDefine().getModuleParameter())
}
Module getModule() { result = m }
}
/**
* A CommonJS/AMD `exports` variable.
*/
private class ExportsVarNode extends DataFlow::Node {
Module m;
ExportsVarNode() {
this.(NodeModuleSourcesNodes).getVariable() = m.(NodeModule).getExportsVariable()
or
DataFlow::parameterNode(this, m.(AmdModule).getDefine().getExportsParameter())
}
Module getModule() { result = m }
}
/** Gets the CommonJS/AMD `module` variable for module `m`. */
SourceNode moduleVarNode(Module m) { result.(ModuleVarNode).getModule() = m }
/** Gets the CommonJS/AMD `exports` variable for module `m`. */
SourceNode exportsVarNode(Module m) { result.(ExportsVarNode).getModule() = m }
deprecated class DefaultSourceNode extends SourceNode {
DefaultSourceNode() { this instanceof SourceNode::DefaultRange }
}

View File

@@ -169,13 +169,19 @@ module CodeInjection {
}
/**
* The first argument to `Module.prototype._compile` from the Node.js built-in module `module`,
* considered as a code-injection sink.
* The first argument to `Module.prototype._compile`, considered as a code-injection sink.
*/
class ModuleCompileSink extends Sink {
ModuleCompileSink() {
// `require('module').prototype._compile`
this =
API::moduleImport("module").getInstance().getMember("_compile").getACall().getArgument(0)
or
// `module.constructor.prototype._compile`
exists(DataFlow::SourceNode moduleConstructor |
moduleConstructor = DataFlow::moduleVarNode(_).getAPropertyRead("constructor") and
this = moduleConstructor.getAnInstantiation().getAMethodCall("_compile").getArgument(0)
)
}
}