mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge remote-tracking branch 'upstream/master' into FalsySanitizer
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
- [lazy-cache](https://www.npmjs.com/package/lazy-cache)
|
||||
- [for-in](https://www.npmjs.com/package/for-in)
|
||||
- [for-own](https://www.npmjs.com/package/for-own)
|
||||
- [send](https://www.npmjs.com/package/send)
|
||||
|
||||
## New queries
|
||||
|
||||
|
||||
@@ -139,6 +139,13 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
/** Gets a parameter of this function. */
|
||||
Parameter getAParameter() { params(unresolveElement(result), underlyingElement(this), _, _) }
|
||||
|
||||
/**
|
||||
* Gets an access of this function.
|
||||
*
|
||||
* To get calls to this function, use `getACallToThisFunction` instead.
|
||||
*/
|
||||
FunctionAccess getAnAccess() { result.getTarget() = this }
|
||||
|
||||
/**
|
||||
* Gets the number of parameters of this function, _not_ including any
|
||||
* implicit `this` parameter or any `...` varargs pseudo-parameter.
|
||||
@@ -174,6 +181,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
result = getParameter(index).getTypedName() + ", " + getParameterStringFrom(index + 1)
|
||||
}
|
||||
|
||||
/** Gets a call to this function. */
|
||||
FunctionCall getACallToThisFunction() { result.getTarget() = this }
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,157 +14,7 @@
|
||||
import javascript
|
||||
import DataFlow
|
||||
import PathGraph
|
||||
import semmle.javascript.dataflow.InferredTypes
|
||||
import semmle.javascript.dataflow.internal.FlowSteps
|
||||
|
||||
/**
|
||||
* Gets a node that refers to an element of `array`, likely obtained
|
||||
* as a result of enumerating the elements of the array.
|
||||
*/
|
||||
SourceNode getAnEnumeratedArrayElement(SourceNode array) {
|
||||
exists(MethodCallNode call, string name |
|
||||
call = array.getAMethodCall(name) and
|
||||
(name = "forEach" or name = "map") and
|
||||
result = call.getCallback(0).getParameter(0)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::PropRead read |
|
||||
read = array.getAPropertyRead() and
|
||||
not exists(read.getPropertyName()) and
|
||||
not read.getPropertyNameExpr().analyze().getAType() = TTString() and
|
||||
result = read
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node that refers to the name of a property obtained by enumerating
|
||||
* the properties of some object.
|
||||
*/
|
||||
abstract class EnumeratedPropName extends DataFlow::Node {
|
||||
/**
|
||||
* Gets the data flow node holding the object whose properties are being enumerated.
|
||||
*
|
||||
* For example, gets `src` in `for (var key in src)`.
|
||||
*/
|
||||
abstract DataFlow::Node getSourceObject();
|
||||
|
||||
/**
|
||||
* Gets a source node that refers to the object whose properties are being enumerated.
|
||||
*/
|
||||
DataFlow::SourceNode getASourceObjectRef() {
|
||||
result = AccessPath::getAnAliasedSourceNode(getSourceObject())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a property read that accesses the corresponding property value in the source object.
|
||||
*
|
||||
* For example, gets `src[key]` in `for (var key in src) { src[key]; }`.
|
||||
*/
|
||||
SourceNode getASourceProp() {
|
||||
exists(Node base, Node key |
|
||||
dynamicPropReadStep(base, key, result) and
|
||||
getASourceObjectRef().flowsTo(base) and
|
||||
key.getImmediatePredecessor*() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Property enumeration through `for-in` for `Object.keys` or similar.
|
||||
*/
|
||||
class ForInEnumeratedPropName extends EnumeratedPropName {
|
||||
DataFlow::Node object;
|
||||
|
||||
ForInEnumeratedPropName() {
|
||||
exists(ForInStmt stmt |
|
||||
this = DataFlow::lvalueNode(stmt.getLValue()) and
|
||||
object = stmt.getIterationDomain().flow()
|
||||
)
|
||||
or
|
||||
exists(CallNode call |
|
||||
call = globalVarRef("Object").getAMemberCall("keys")
|
||||
or
|
||||
call = globalVarRef("Object").getAMemberCall("getOwnPropertyNames")
|
||||
or
|
||||
call = globalVarRef("Reflect").getAMemberCall("ownKeys")
|
||||
|
|
||||
object = call.getArgument(0) and
|
||||
this = getAnEnumeratedArrayElement(call)
|
||||
)
|
||||
}
|
||||
|
||||
override Node getSourceObject() { result = object }
|
||||
}
|
||||
|
||||
/**
|
||||
* Property enumeration through `Object.entries`.
|
||||
*/
|
||||
class EntriesEnumeratedPropName extends EnumeratedPropName {
|
||||
CallNode entries;
|
||||
SourceNode entry;
|
||||
|
||||
EntriesEnumeratedPropName() {
|
||||
entries = globalVarRef("Object").getAMemberCall("entries") and
|
||||
entry = getAnEnumeratedArrayElement(entries) and
|
||||
this = entry.getAPropertyRead("0")
|
||||
}
|
||||
|
||||
override DataFlow::Node getSourceObject() {
|
||||
result = entries.getArgument(0)
|
||||
}
|
||||
|
||||
override SourceNode getASourceProp() {
|
||||
result = super.getASourceProp()
|
||||
or
|
||||
result = entry.getAPropertyRead("1")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a function that enumerates object properties when invoked.
|
||||
*
|
||||
* Invocations takes the following form:
|
||||
* ```js
|
||||
* fn(obj, (value, key, o) => { ... })
|
||||
* ```
|
||||
*/
|
||||
SourceNode propertyEnumerator() {
|
||||
result = moduleImport("for-own") or
|
||||
result = moduleImport("for-in") or
|
||||
result = moduleMember("ramda", "forEachObjIndexed") or
|
||||
result = LodashUnderscore::member("forEach") or
|
||||
result = LodashUnderscore::member("each")
|
||||
}
|
||||
|
||||
/**
|
||||
* Property enumeration through a library function taking a callback.
|
||||
*/
|
||||
class LibraryCallbackEnumeratedPropName extends EnumeratedPropName {
|
||||
CallNode call;
|
||||
FunctionNode callback;
|
||||
|
||||
LibraryCallbackEnumeratedPropName() {
|
||||
call = propertyEnumerator().getACall() and
|
||||
callback = call.getCallback(1) and
|
||||
this = callback.getParameter(1)
|
||||
}
|
||||
|
||||
override Node getSourceObject() {
|
||||
result = call.getArgument(0)
|
||||
}
|
||||
|
||||
override SourceNode getASourceObjectRef() {
|
||||
result = super.getASourceObjectRef()
|
||||
or
|
||||
result = callback.getParameter(2)
|
||||
}
|
||||
|
||||
override SourceNode getASourceProp() {
|
||||
result = super.getASourceProp()
|
||||
or
|
||||
result = callback.getParameter(0)
|
||||
}
|
||||
}
|
||||
import semmle.javascript.DynamicPropertyAccess
|
||||
|
||||
/**
|
||||
* Holds if the properties of `node` are enumerated locally.
|
||||
@@ -173,72 +23,6 @@ predicate arePropertiesEnumerated(DataFlow::SourceNode node) {
|
||||
node = any(EnumeratedPropName name).getASourceObjectRef()
|
||||
}
|
||||
|
||||
/**
|
||||
* A dynamic property access that is not obviously an array access.
|
||||
*/
|
||||
class DynamicPropRead extends DataFlow::SourceNode, DataFlow::ValueNode {
|
||||
// Use IndexExpr instead of PropRead as we're not interested in implicit accesses like
|
||||
// rest-patterns and for-of loops.
|
||||
override IndexExpr astNode;
|
||||
|
||||
DynamicPropRead() {
|
||||
not exists(astNode.getPropertyName()) and
|
||||
// Exclude obvious array access
|
||||
astNode.getPropertyNameExpr().analyze().getAType() = TTString()
|
||||
}
|
||||
|
||||
/** Gets the base of the dynamic read. */
|
||||
DataFlow::Node getBase() { result = astNode.getBase().flow() }
|
||||
|
||||
/** Gets the node holding the name of the property. */
|
||||
DataFlow::Node getPropertyNameNode() { result = astNode.getIndex().flow() }
|
||||
|
||||
/**
|
||||
* Holds if the value of this read was assigned to earlier in the same basic block.
|
||||
*
|
||||
* For example, this is true for `dst[x]` on line 2 below:
|
||||
* ```js
|
||||
* dst[x] = {};
|
||||
* dst[x][y] = src[y];
|
||||
* ```
|
||||
*/
|
||||
predicate hasDominatingAssignment() {
|
||||
exists(DataFlow::PropWrite write, BasicBlock bb, int i, int j, SsaVariable ssaVar |
|
||||
write = getBase().getALocalSource().getAPropertyWrite() and
|
||||
bb.getNode(i) = write.getWriteNode() and
|
||||
bb.getNode(j) = astNode and
|
||||
i < j and
|
||||
write.getPropertyNameExpr() = ssaVar.getAUse() and
|
||||
astNode.getIndex() = ssaVar.getAUse()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `output` is the result of `base[key]`, either directly or through
|
||||
* one or more function calls, ignoring reads that can't access the prototype chain.
|
||||
*/
|
||||
predicate dynamicPropReadStep(Node base, Node key, SourceNode output) {
|
||||
exists(DynamicPropRead read |
|
||||
not read.hasDominatingAssignment() and
|
||||
base = read.getBase() and
|
||||
key = read.getPropertyNameNode() and
|
||||
output = read
|
||||
)
|
||||
or
|
||||
// Summarize functions returning a dynamic property read of two parameters, such as `function getProp(obj, prop) { return obj[prop]; }`.
|
||||
exists(CallNode call, Function callee, ParameterNode baseParam, ParameterNode keyParam, Node innerBase, Node innerKey, SourceNode innerOutput |
|
||||
dynamicPropReadStep(innerBase, innerKey, innerOutput) and
|
||||
baseParam.flowsTo(innerBase) and
|
||||
keyParam.flowsTo(innerKey) and
|
||||
innerOutput.flowsTo(callee.getAReturnedExpr().flow()) and
|
||||
call.getACallee() = callee and
|
||||
argumentPassingStep(call, base, callee, baseParam) and
|
||||
argumentPassingStep(call, key, callee, keyParam) and
|
||||
output = call
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` may flow from an enumerated prop name, possibly
|
||||
* into function calls (but not returns).
|
||||
|
||||
222
javascript/ql/src/semmle/javascript/DynamicPropertyAccess.qll
Normal file
222
javascript/ql/src/semmle/javascript/DynamicPropertyAccess.qll
Normal file
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* Provides classes for working with dynamic property accesses.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
private import semmle.javascript.dataflow.DataFlow::DataFlow
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps
|
||||
|
||||
/**
|
||||
* Gets a node that refers to an element of `array`, likely obtained
|
||||
* as a result of enumerating the elements of the array.
|
||||
*/
|
||||
private SourceNode getAnEnumeratedArrayElement(SourceNode array) {
|
||||
exists(MethodCallNode call, string name |
|
||||
call = array.getAMethodCall(name) and
|
||||
(name = "forEach" or name = "map") and
|
||||
result = call.getCallback(0).getParameter(0)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::PropRead read |
|
||||
read = array.getAPropertyRead() and
|
||||
not exists(read.getPropertyName()) and
|
||||
not read.getPropertyNameExpr().analyze().getAType() = TTString() and
|
||||
result = read
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node that refers to the name of a property obtained by enumerating
|
||||
* the properties of some object.
|
||||
*/
|
||||
abstract class EnumeratedPropName extends DataFlow::Node {
|
||||
/**
|
||||
* Gets the data flow node holding the object whose properties are being enumerated.
|
||||
*
|
||||
* For example, gets `src` in `for (var key in src)`.
|
||||
*/
|
||||
abstract DataFlow::Node getSourceObject();
|
||||
|
||||
/**
|
||||
* Gets a source node that refers to the object whose properties are being enumerated.
|
||||
*/
|
||||
DataFlow::SourceNode getASourceObjectRef() {
|
||||
result = AccessPath::getAnAliasedSourceNode(getSourceObject())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a property read that accesses the corresponding property value in the source object.
|
||||
*
|
||||
* For example, gets `src[key]` in `for (var key in src) { src[key]; }`.
|
||||
*/
|
||||
SourceNode getASourceProp() {
|
||||
exists(Node base, Node key |
|
||||
dynamicPropReadStep(base, key, result) and
|
||||
getASourceObjectRef().flowsTo(base) and
|
||||
key.getImmediatePredecessor*() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Property enumeration through `for-in` for `Object.keys` or similar.
|
||||
*/
|
||||
private class ForInEnumeratedPropName extends EnumeratedPropName {
|
||||
DataFlow::Node object;
|
||||
|
||||
ForInEnumeratedPropName() {
|
||||
exists(ForInStmt stmt |
|
||||
this = DataFlow::lvalueNode(stmt.getLValue()) and
|
||||
object = stmt.getIterationDomain().flow()
|
||||
)
|
||||
or
|
||||
exists(CallNode call |
|
||||
call = globalVarRef("Object").getAMemberCall("keys")
|
||||
or
|
||||
call = globalVarRef("Object").getAMemberCall("getOwnPropertyNames")
|
||||
or
|
||||
call = globalVarRef("Reflect").getAMemberCall("ownKeys")
|
||||
|
|
||||
object = call.getArgument(0) and
|
||||
this = getAnEnumeratedArrayElement(call)
|
||||
)
|
||||
}
|
||||
|
||||
override Node getSourceObject() { result = object }
|
||||
}
|
||||
|
||||
/**
|
||||
* Property enumeration through `Object.entries`.
|
||||
*/
|
||||
private class EntriesEnumeratedPropName extends EnumeratedPropName {
|
||||
CallNode entries;
|
||||
SourceNode entry;
|
||||
|
||||
EntriesEnumeratedPropName() {
|
||||
entries = globalVarRef("Object").getAMemberCall("entries") and
|
||||
entry = getAnEnumeratedArrayElement(entries) and
|
||||
this = entry.getAPropertyRead("0")
|
||||
}
|
||||
|
||||
override DataFlow::Node getSourceObject() { result = entries.getArgument(0) }
|
||||
|
||||
override SourceNode getASourceProp() {
|
||||
result = super.getASourceProp()
|
||||
or
|
||||
result = entry.getAPropertyRead("1")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a function that enumerates object properties when invoked.
|
||||
*
|
||||
* Invocations takes the following form:
|
||||
* ```js
|
||||
* fn(obj, (value, key, o) => { ... })
|
||||
* ```
|
||||
*/
|
||||
private SourceNode propertyEnumerator() {
|
||||
result = moduleImport("for-own") or
|
||||
result = moduleImport("for-in") or
|
||||
result = moduleMember("ramda", "forEachObjIndexed") or
|
||||
result = LodashUnderscore::member("forEach") or
|
||||
result = LodashUnderscore::member("each")
|
||||
}
|
||||
|
||||
/**
|
||||
* Property enumeration through a library function taking a callback.
|
||||
*/
|
||||
private class LibraryCallbackEnumeratedPropName extends EnumeratedPropName {
|
||||
CallNode call;
|
||||
FunctionNode callback;
|
||||
|
||||
LibraryCallbackEnumeratedPropName() {
|
||||
call = propertyEnumerator().getACall() and
|
||||
callback = call.getCallback(1) and
|
||||
this = callback.getParameter(1)
|
||||
}
|
||||
|
||||
override Node getSourceObject() { result = call.getArgument(0) }
|
||||
|
||||
override SourceNode getASourceObjectRef() {
|
||||
result = super.getASourceObjectRef()
|
||||
or
|
||||
result = callback.getParameter(2)
|
||||
}
|
||||
|
||||
override SourceNode getASourceProp() {
|
||||
result = super.getASourceProp()
|
||||
or
|
||||
result = callback.getParameter(0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dynamic property access that is not obviously an array access.
|
||||
*/
|
||||
class DynamicPropRead extends DataFlow::SourceNode, DataFlow::ValueNode {
|
||||
// Use IndexExpr instead of PropRead as we're not interested in implicit accesses like
|
||||
// rest-patterns and for-of loops.
|
||||
override IndexExpr astNode;
|
||||
|
||||
DynamicPropRead() {
|
||||
not exists(astNode.getPropertyName()) and
|
||||
// Exclude obvious array access
|
||||
astNode.getPropertyNameExpr().analyze().getAType() = TTString()
|
||||
}
|
||||
|
||||
/** Gets the base of the dynamic read. */
|
||||
DataFlow::Node getBase() { result = astNode.getBase().flow() }
|
||||
|
||||
/** Gets the node holding the name of the property. */
|
||||
DataFlow::Node getPropertyNameNode() { result = astNode.getIndex().flow() }
|
||||
|
||||
/**
|
||||
* Holds if the value of this read was assigned to earlier in the same basic block.
|
||||
*
|
||||
* For example, this is true for `dst[x]` on line 2 below:
|
||||
* ```js
|
||||
* dst[x] = {};
|
||||
* dst[x][y] = src[y];
|
||||
* ```
|
||||
*/
|
||||
predicate hasDominatingAssignment() {
|
||||
exists(DataFlow::PropWrite write, BasicBlock bb, int i, int j, SsaVariable ssaVar |
|
||||
write = getBase().getALocalSource().getAPropertyWrite() and
|
||||
bb.getNode(i) = write.getWriteNode() and
|
||||
bb.getNode(j) = astNode and
|
||||
i < j and
|
||||
write.getPropertyNameExpr() = ssaVar.getAUse() and
|
||||
astNode.getIndex() = ssaVar.getAUse()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `output` is the result of `base[key]`, either directly or through
|
||||
* one or more function calls, ignoring reads that can't access the prototype chain.
|
||||
*/
|
||||
predicate dynamicPropReadStep(Node base, Node key, SourceNode output) {
|
||||
exists(DynamicPropRead read |
|
||||
not read.hasDominatingAssignment() and
|
||||
base = read.getBase() and
|
||||
key = read.getPropertyNameNode() and
|
||||
output = read
|
||||
)
|
||||
or
|
||||
// Summarize functions returning a dynamic property read of two parameters, such as `function getProp(obj, prop) { return obj[prop]; }`.
|
||||
exists(
|
||||
CallNode call, Function callee, ParameterNode baseParam, ParameterNode keyParam, Node innerBase,
|
||||
Node innerKey, SourceNode innerOutput
|
||||
|
|
||||
dynamicPropReadStep(innerBase, innerKey, innerOutput) and
|
||||
baseParam.flowsTo(innerBase) and
|
||||
keyParam.flowsTo(innerKey) and
|
||||
innerOutput.flowsTo(callee.getAReturnedExpr().flow()) and
|
||||
call.getACallee() = callee and
|
||||
argumentPassingStep(call, base, callee, baseParam) and
|
||||
argumentPassingStep(call, key, callee, keyParam) and
|
||||
output = call
|
||||
)
|
||||
}
|
||||
@@ -428,4 +428,11 @@ module TaintedPath {
|
||||
class AngularJSTemplateUrlSink extends Sink, DataFlow::ValueNode {
|
||||
AngularJSTemplateUrlSink() { this = any(AngularJS::CustomDirective d).getMember("templateUrl") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The path argument of a [send](https://www.npmjs.com/package/send) call, viewed as a sink.
|
||||
*/
|
||||
class SendPathSink extends Sink, DataFlow::ValueNode {
|
||||
SendPathSink() { this = DataFlow::moduleImport("send").getACall().getArgument(1) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,6 +801,92 @@ nodes
|
||||
| TaintedPath.js:112:45:112:52 | realpath |
|
||||
| TaintedPath.js:112:45:112:52 | realpath |
|
||||
| TaintedPath.js:112:45:112:52 | realpath |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:23:143:29 | req.url |
|
||||
| TaintedPath.js:143:23:143:29 | req.url |
|
||||
| TaintedPath.js:143:23:143:29 | req.url |
|
||||
| TaintedPath.js:143:23:143:29 | req.url |
|
||||
| TaintedPath.js:143:23:143:29 | req.url |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:145:23:145:26 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path |
|
||||
@@ -2996,6 +3082,118 @@ edges
|
||||
| TaintedPath.js:111:32:111:39 | realpath | TaintedPath.js:112:45:112:52 | realpath |
|
||||
| TaintedPath.js:111:32:111:39 | realpath | TaintedPath.js:112:45:112:52 | realpath |
|
||||
| TaintedPath.js:111:32:111:39 | realpath | TaintedPath.js:112:45:112:52 | realpath |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:6:143:47 | path | TaintedPath.js:145:23:145:26 | path |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:36 | url.par ... , true) | TaintedPath.js:143:13:143:42 | url.par ... ).query |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:42 | url.par ... ).query | TaintedPath.js:143:13:143:47 | url.par ... ry.path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:13:143:47 | url.par ... ry.path | TaintedPath.js:143:6:143:47 | path |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:143:13:143:36 | url.par ... , true) |
|
||||
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
|
||||
@@ -4171,6 +4369,7 @@ edges
|
||||
| TaintedPath.js:94:48:94:60 | req.params[0] | TaintedPath.js:94:48:94:60 | req.params[0] | TaintedPath.js:94:48:94:60 | req.params[0] | This path depends on $@. | TaintedPath.js:94:48:94:60 | req.params[0] | a user-provided value |
|
||||
| TaintedPath.js:109:28:109:48 | fs.real ... c(path) | TaintedPath.js:107:23:107:29 | req.url | TaintedPath.js:109:28:109:48 | fs.real ... c(path) | This path depends on $@. | TaintedPath.js:107:23:107:29 | req.url | a user-provided value |
|
||||
| TaintedPath.js:112:45:112:52 | realpath | TaintedPath.js:107:23:107:29 | req.url | TaintedPath.js:112:45:112:52 | realpath | This path depends on $@. | TaintedPath.js:107:23:107:29 | req.url | a user-provided value |
|
||||
| TaintedPath.js:145:23:145:26 | path | TaintedPath.js:143:23:143:29 | req.url | TaintedPath.js:145:23:145:26 | path | This path depends on $@. | TaintedPath.js:143:23:143:29 | req.url | a user-provided value |
|
||||
| normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
|
||||
| normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
|
||||
| normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
|
||||
|
||||
@@ -138,3 +138,9 @@ var server = http.createServer(function(req, res) {
|
||||
|
||||
res.write(fs.readFileSync(path)); // OK. Is sanitized above.
|
||||
});
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
let path = url.parse(req.url, true).query.path;
|
||||
|
||||
require('send')(req, path); // NOT OK
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user