mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
JS: Mass rename to node1,state1,node2,state2 naming convention
This commit is contained in:
@@ -18,9 +18,9 @@ module IdorTaintConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isSink(DataFlow::Node node) { exists(ClientRequest req | node = req.getADataNode()) }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// Step from x -> { userId: x }
|
||||
succ.(DataFlow::SourceNode).getAPropertyWrite("userId").getRhs() = pred
|
||||
node2.(DataFlow::SourceNode).getAPropertyWrite("userId").getRhs() = node1
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
|
||||
@@ -37,16 +37,16 @@ module AuthKeyTrackingConfig implements DataFlow::ConfigSig {
|
||||
)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// Step into objects: x -> { f: x }
|
||||
succ.(DataFlow::SourceNode).getAPropertyWrite().getRhs() = pred
|
||||
node2.(DataFlow::SourceNode).getAPropertyWrite().getRhs() = node1
|
||||
or
|
||||
// Step through JSON serialization: x -> JSON.stringify(x)
|
||||
// Note: TaintTracking::Configuration includes this step by default, but not DataFlow::Configuration
|
||||
exists(DataFlow::CallNode call |
|
||||
call = DataFlow::globalVarRef("JSON").getAMethodCall("stringify") and
|
||||
pred = call.getArgument(0) and
|
||||
succ = call
|
||||
node1 = call.getArgument(0) and
|
||||
node2 = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,42 +36,42 @@ module TaintedObject {
|
||||
/**
|
||||
* Holds for the flows steps that are relevant for tracking user-controlled JSON objects.
|
||||
*/
|
||||
predicate isAdditionalFlowStep(Node src, FlowState inlbl, Node trg, FlowState outlbl) {
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
// JSON parsers map tainted inputs to tainted JSON
|
||||
inlbl.isTaint() and
|
||||
outlbl.isTaintedObject() and
|
||||
state1.isTaint() and
|
||||
state2.isTaintedObject() and
|
||||
exists(JsonParserCall parse |
|
||||
src = parse.getInput() and
|
||||
trg = parse.getOutput()
|
||||
node1 = parse.getInput() and
|
||||
node2 = parse.getOutput()
|
||||
)
|
||||
or
|
||||
// Property reads preserve deep object taint.
|
||||
inlbl.isTaintedObject() and
|
||||
outlbl.isTaintedObject() and
|
||||
trg.(PropRead).getBase() = src
|
||||
state1.isTaintedObject() and
|
||||
state2.isTaintedObject() and
|
||||
node2.(PropRead).getBase() = node1
|
||||
or
|
||||
// Property projection preserves deep object taint
|
||||
inlbl.isTaintedObject() and
|
||||
outlbl.isTaintedObject() and
|
||||
trg.(PropertyProjection).getObject() = src
|
||||
state1.isTaintedObject() and
|
||||
state2.isTaintedObject() and
|
||||
node2.(PropertyProjection).getObject() = node1
|
||||
or
|
||||
// Extending objects preserves deep object taint
|
||||
inlbl.isTaintedObject() and
|
||||
outlbl.isTaintedObject() and
|
||||
state1.isTaintedObject() and
|
||||
state2.isTaintedObject() and
|
||||
exists(ExtendCall call |
|
||||
src = call.getAnOperand() and
|
||||
trg = call
|
||||
node1 = call.getAnOperand() and
|
||||
node2 = call
|
||||
or
|
||||
src = call.getASourceOperand() and
|
||||
trg = call.getDestinationOperand().getALocalSource()
|
||||
node1 = call.getASourceOperand() and
|
||||
node2 = call.getDestinationOperand().getALocalSource()
|
||||
)
|
||||
or
|
||||
// Spreading into an object preserves deep object taint: `p -> { ...p }`
|
||||
inlbl.isTaintedObject() and
|
||||
outlbl.isTaintedObject() and
|
||||
state1.isTaintedObject() and
|
||||
state2.isTaintedObject() and
|
||||
exists(ObjectLiteralNode obj |
|
||||
src = obj.getASpreadProperty() and
|
||||
trg = obj
|
||||
node1 = obj.getASpreadProperty() and
|
||||
node2 = obj
|
||||
)
|
||||
}
|
||||
|
||||
@@ -96,8 +96,8 @@ module TaintedObject {
|
||||
/** Holds if this node blocks flow through `e`, provided it evaluates to `outcome`. */
|
||||
predicate blocksExpr(boolean outcome, Expr e) { none() }
|
||||
|
||||
/** Holds if this node blocks flow of `label` through `e`, provided it evaluates to `outcome`. */
|
||||
predicate blocksExpr(boolean outcome, Expr e, FlowState label) { none() }
|
||||
/** Holds if this node blocks flow of `state` through `e`, provided it evaluates to `outcome`. */
|
||||
predicate blocksExpr(boolean outcome, Expr e, FlowState state) { none() }
|
||||
|
||||
/** DEPRECATED. Use `blocksExpr` instead. */
|
||||
deprecated predicate sanitizes(boolean outcome, Expr e, FlowLabel label) {
|
||||
|
||||
@@ -66,11 +66,11 @@ module TaintedUrlSuffix {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a flow step `src -> dst` involving the URL suffix flow state.
|
||||
* Holds if there is a flow step `node1 -> node2` involving the URL suffix flow state.
|
||||
*
|
||||
* This handles steps through string operations, promises, URL parsers, and URL accessors.
|
||||
*/
|
||||
predicate isAdditionalFlowStep(Node src, FlowState srclbl, Node dst, FlowState dstlbl) {
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
// Transition from tainted-url-suffix to general taint when entering the second array element
|
||||
// of a split('#') or split('?') array.
|
||||
//
|
||||
@@ -79,17 +79,17 @@ module TaintedUrlSuffix {
|
||||
// Technically we should also preverse tainted-url-suffix when entering the first array element of such
|
||||
// a split, but this mostly leads to FPs since we currently don't track if the taint has been through URI-decoding.
|
||||
// (The query/fragment parts are often URI-decoded in practice, but not the other URL parts are not)
|
||||
srclbl.isTaintedUrlSuffix() and
|
||||
dstlbl.isTaint() and
|
||||
DataFlowPrivate::optionalStep(src, "split-url-suffix-post", dst)
|
||||
state1.isTaintedUrlSuffix() and
|
||||
state2.isTaint() and
|
||||
DataFlowPrivate::optionalStep(node1, "split-url-suffix-post", node2)
|
||||
or
|
||||
// Transition from URL suffix to full taint when extracting the query/fragment part.
|
||||
srclbl.isTaintedUrlSuffix() and
|
||||
dstlbl.isTaint() and
|
||||
state1.isTaintedUrlSuffix() and
|
||||
state2.isTaint() and
|
||||
(
|
||||
exists(MethodCallNode call, string name |
|
||||
src = call.getReceiver() and
|
||||
dst = call and
|
||||
node1 = call.getReceiver() and
|
||||
node2 = call and
|
||||
name = call.getMethodName()
|
||||
|
|
||||
// Substring that is not a prefix
|
||||
@@ -118,8 +118,8 @@ module TaintedUrlSuffix {
|
||||
)
|
||||
or
|
||||
exists(PropRead read |
|
||||
src = read.getBase() and
|
||||
dst = read and
|
||||
node1 = read.getBase() and
|
||||
node2 = read and
|
||||
// Unlike the `search` property, the `query` property from `url.parse` does not include the `?`.
|
||||
read.getPropertyName() = "query"
|
||||
)
|
||||
@@ -127,13 +127,13 @@ module TaintedUrlSuffix {
|
||||
exists(MethodCallNode call, DataFlow::RegExpCreationNode re |
|
||||
(
|
||||
call = re.getAMethodCall("exec") and
|
||||
src = call.getArgument(0) and
|
||||
dst = call
|
||||
node1 = call.getArgument(0) and
|
||||
node2 = call
|
||||
or
|
||||
call.getMethodName() = ["match", "matchAll"] and
|
||||
re.flowsTo(call.getArgument(0)) and
|
||||
src = call.getReceiver() and
|
||||
dst = call
|
||||
node1 = call.getReceiver() and
|
||||
node2 = call
|
||||
)
|
||||
|
|
||||
captureAfterSuffixIndicator(re.getRoot().getAChild*())
|
||||
|
||||
@@ -21,8 +21,8 @@ module BuildArtifactLeakConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof CleartextLogging::Barrier }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) {
|
||||
CleartextLogging::isAdditionalTaintStep(src, trg)
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
CleartextLogging::isAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet contents) {
|
||||
|
||||
@@ -32,8 +32,8 @@ module CleartextLoggingConfig implements DataFlow::ConfigSig {
|
||||
isSource(node)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) {
|
||||
CleartextLogging::isAdditionalTaintStep(src, trg)
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
CleartextLogging::isAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet contents) {
|
||||
|
||||
@@ -28,8 +28,8 @@ module ClientSideRequestForgeryConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) { sanitizingPrefixEdge(node, _) }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
isAdditionalRequestForgeryStep(pred, succ)
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalRequestForgeryStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ module ClientSideUrlRedirectConfig implements DataFlow::StateConfigSig {
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) { hostnameSanitizingPrefixEdge(node, _) }
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node, FlowState label) { isSink(node, label) }
|
||||
predicate isBarrierOut(DataFlow::Node node, FlowState state) { isSink(node, state) }
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
|
||||
@@ -20,9 +20,9 @@ module ConditionalBypassConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node dst) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// comparing a tainted expression against a constant gives a tainted result
|
||||
dst.asExpr().(Comparison).hasOperands(src.asExpr(), any(ConstantExpr c))
|
||||
node2.asExpr().(Comparison).hasOperands(node1.asExpr(), any(ConstantExpr c))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -146,12 +146,12 @@ module ExceptionXssConfig implements DataFlow::StateConfigSig {
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node pred, FlowState inlbl, DataFlow::Node succ, FlowState outlbl
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
inlbl = FlowState::notYetThrown() and
|
||||
outlbl = [FlowState::thrown(), FlowState::notYetThrown()] and
|
||||
canThrowSensitiveInformation(pred) and
|
||||
succ = getExceptionTarget(pred)
|
||||
state1 = FlowState::notYetThrown() and
|
||||
state2 = [FlowState::thrown(), FlowState::notYetThrown()] and
|
||||
canThrowSensitiveInformation(node1) and
|
||||
node2 = getExceptionTarget(node1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,54 +19,54 @@ module HardcodedCredentialsConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) {
|
||||
exists(Base64::Encode encode | src = encode.getInput() and trg = encode.getOutput())
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(Base64::Encode encode | node1 = encode.getInput() and node2 = encode.getOutput())
|
||||
or
|
||||
trg.(StringOps::ConcatenationRoot).getALeaf() = src and
|
||||
not exists(src.(StringOps::ConcatenationLeaf).getStringValue()) // to avoid e.g. the ":" in `user + ":" + pass` being flagged as a constant credential.
|
||||
node2.(StringOps::ConcatenationRoot).getALeaf() = node1 and
|
||||
not exists(node1.(StringOps::ConcatenationLeaf).getStringValue()) // to avoid e.g. the ":" in `user + ":" + pass` being flagged as a constant credential.
|
||||
or
|
||||
exists(DataFlow::MethodCallNode bufferFrom |
|
||||
bufferFrom = DataFlow::globalVarRef("Buffer").getAMethodCall("from") and
|
||||
trg = bufferFrom and
|
||||
src = bufferFrom.getArgument(0)
|
||||
node2 = bufferFrom and
|
||||
node1 = bufferFrom.getArgument(0)
|
||||
)
|
||||
or
|
||||
exists(API::Node n |
|
||||
n = API::moduleImport("jose").getMember(["importSPKI", "importPKCS8", "importX509"])
|
||||
|
|
||||
src = n.getACall().getArgument(0) and
|
||||
trg = n.getReturn().getPromised().asSource()
|
||||
node1 = n.getACall().getArgument(0) and
|
||||
node2 = n.getReturn().getPromised().asSource()
|
||||
)
|
||||
or
|
||||
exists(API::Node n |
|
||||
n = API::moduleImport("jose").getMember(["importSPKI", "importPKCS8", "importX509"])
|
||||
|
|
||||
src = n.getACall().getArgument(0) and
|
||||
trg = n.getReturn().getPromised().asSource()
|
||||
node1 = n.getACall().getArgument(0) and
|
||||
node2 = n.getReturn().getPromised().asSource()
|
||||
)
|
||||
or
|
||||
exists(API::Node n | n = API::moduleImport("jose").getMember("importJWK") |
|
||||
src = n.getParameter(0).getMember(["x", "y", "n"]).asSink() and
|
||||
trg = n.getReturn().getPromised().asSource()
|
||||
node1 = n.getParameter(0).getMember(["x", "y", "n"]).asSink() and
|
||||
node2 = n.getReturn().getPromised().asSource()
|
||||
)
|
||||
or
|
||||
exists(DataFlow::CallNode n |
|
||||
n = DataFlow::globalVarRef("TextEncoder").getAnInstantiation().getAMemberCall("encode")
|
||||
|
|
||||
src = n.getArgument(0) and
|
||||
trg = n
|
||||
node1 = n.getArgument(0) and
|
||||
node2 = n
|
||||
)
|
||||
or
|
||||
exists(DataFlow::CallNode n | n = DataFlow::globalVarRef("Buffer").getAMemberCall("from") |
|
||||
src = n.getArgument(0) and
|
||||
trg = [n, n.getAChainedMethodCall(["toString", "toJSON"])]
|
||||
node1 = n.getArgument(0) and
|
||||
node2 = [n, n.getAChainedMethodCall(["toString", "toJSON"])]
|
||||
)
|
||||
or
|
||||
exists(API::Node n |
|
||||
n = API::moduleImport("jose").getMember("base64url").getMember(["decode", "encode"])
|
||||
|
|
||||
src = n.getACall().getArgument(0) and
|
||||
trg = n.getACall()
|
||||
node1 = n.getACall().getArgument(0) and
|
||||
node2 = n.getACall()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,11 @@ private import HardcodedDataInterpretedAsCodeCustomizations::HardcodedDataInterp
|
||||
module HardcodedDataInterpretedAsCodeConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = HardcodedDataInterpretedAsCode::FlowState;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState lbl) { source.(Source).getAFlowState() = lbl }
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
source.(Source).getAFlowState() = state
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node nd, FlowState lbl) { nd.(Sink).getAFlowState() = lbl }
|
||||
predicate isSink(DataFlow::Node nd, FlowState state) { nd.(Sink).getAFlowState() = state }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
|
||||
@@ -29,16 +29,16 @@ deprecated private module Label {
|
||||
module IncompleteHtmlAttributeSanitizationConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = IncompleteHtmlAttributeSanitization::FlowState;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState label) {
|
||||
label = FlowState::character(source.(Source).getAnUnsanitizedCharacter())
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
state = FlowState::character(source.(Source).getAnUnsanitizedCharacter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState label) {
|
||||
label = FlowState::character(sink.(Sink).getADangerousCharacter())
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
state = FlowState::character(sink.(Sink).getADangerousCharacter())
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState lbl) {
|
||||
lbl = FlowState::character(node.(StringReplaceCall).getAReplacedString())
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) {
|
||||
state = FlowState::character(node.(StringReplaceCall).getAReplacedString())
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node n) { n instanceof Sanitizer }
|
||||
|
||||
@@ -32,13 +32,13 @@ module InsecureRandomnessConfig implements DataFlow::ConfigSig {
|
||||
isSink(node)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
InsecureRandomness::isAdditionalTaintStep(pred, succ)
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
InsecureRandomness::isAdditionalTaintStep(node1, node2)
|
||||
or
|
||||
// We want to make use of default taint steps but not the default taint sanitizers, as they
|
||||
// generally assume numbers aren't taintable. So we use a data-flow configuration that includes all
|
||||
// taint steps as additional flow steps.
|
||||
TaintTracking::defaultTaintStep(pred, succ)
|
||||
TaintTracking::defaultTaintStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ module LoopBoundInjectionConfig implements DataFlow::StateConfigSig {
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node src, FlowState inlbl, DataFlow::Node trg, FlowState outlbl
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
TaintedObject::isAdditionalFlowStep(src, inlbl, trg, outlbl)
|
||||
TaintedObject::isAdditionalFlowStep(node1, state1, node2, state2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ deprecated private class ConcreteObjectPrototype extends ObjectPrototype {
|
||||
module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = PrototypePollutingAssignment::FlowState;
|
||||
|
||||
predicate isSource(DataFlow::Node node, FlowState label) {
|
||||
node instanceof Source and label = FlowState::taint()
|
||||
predicate isSource(DataFlow::Node node, FlowState state) {
|
||||
node instanceof Source and state = FlowState::taint()
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node, FlowState lbl) { node.(Sink).getAFlowState() = lbl }
|
||||
predicate isSink(DataFlow::Node node, FlowState state) { node.(Sink).getAFlowState() = state }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node instanceof Sanitizer
|
||||
@@ -58,28 +58,28 @@ module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig {
|
||||
node = DataFlow::MakeBarrierGuard<BarrierGuard>::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node, FlowState lbl) {
|
||||
predicate isBarrierOut(DataFlow::Node node, FlowState state) {
|
||||
// Suppress the value-preserving step src -> dst in `extend(dst, src)`. This is modeled as a value-preserving
|
||||
// step because it preserves all properties, but the destination is not actually Object.prototype.
|
||||
node = any(ExtendCall call).getASourceOperand() and
|
||||
lbl = FlowState::objectPrototype()
|
||||
state = FlowState::objectPrototype()
|
||||
}
|
||||
|
||||
predicate isBarrierIn(DataFlow::Node node, FlowState lbl) {
|
||||
predicate isBarrierIn(DataFlow::Node node, FlowState state) {
|
||||
// FIXME: This should only be an in-barrier for the corresponding flow state, but flow-state specific in-barriers are not supported right now.
|
||||
isSource(node, lbl)
|
||||
isSource(node, state)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node pred, FlowState inlbl, DataFlow::Node succ, FlowState outlbl
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
// Step from x -> obj[x] while switching to the ObjectPrototype label
|
||||
// (If `x` can have the value `__proto__` then the result can be Object.prototype)
|
||||
exists(DynamicPropRead read |
|
||||
pred = read.getPropertyNameNode() and
|
||||
succ = read and
|
||||
inlbl = FlowState::taint() and
|
||||
outlbl = FlowState::objectPrototype() and
|
||||
node1 = read.getPropertyNameNode() and
|
||||
node2 = read and
|
||||
state1 = FlowState::taint() and
|
||||
state2 = FlowState::objectPrototype() and
|
||||
// Exclude cases where the property name came from a property enumeration.
|
||||
// If the property name is an own property of the base object, the read won't
|
||||
// return Object.prototype.
|
||||
@@ -93,10 +93,10 @@ module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig {
|
||||
// Same as above, but for property projection.
|
||||
exists(PropertyProjection proj |
|
||||
proj.isSingletonProjection() and
|
||||
pred = proj.getASelector() and
|
||||
succ = proj and
|
||||
inlbl = FlowState::taint() and
|
||||
outlbl = FlowState::objectPrototype()
|
||||
node1 = proj.getASelector() and
|
||||
node2 = proj and
|
||||
state1 = FlowState::taint() and
|
||||
state2 = FlowState::objectPrototype()
|
||||
)
|
||||
or
|
||||
// TODO: local field step becomes a jump step, resulting in FPs (closure-lib)
|
||||
@@ -104,22 +104,22 @@ module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig {
|
||||
// DataFlow::localFieldStep(pred, succ)
|
||||
none()
|
||||
or
|
||||
inlbl = FlowState::taint() and
|
||||
TaintTracking::defaultTaintStep(pred, succ) and
|
||||
inlbl = outlbl
|
||||
state1 = FlowState::taint() and
|
||||
TaintTracking::defaultTaintStep(node1, node2) and
|
||||
state1 = state2
|
||||
}
|
||||
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState lbl) {
|
||||
lbl = FlowState::taint() and
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) {
|
||||
state = FlowState::taint() and
|
||||
TaintTracking::defaultSanitizer(node)
|
||||
or
|
||||
// Don't propagate into the receiver, as the method lookups will generally fail on Object.prototype.
|
||||
node instanceof DataFlow::ThisNode and
|
||||
lbl = FlowState::objectPrototype()
|
||||
state = FlowState::objectPrototype()
|
||||
or
|
||||
node = DataFlow::MakeStateBarrierGuard<FlowState, BarrierGuard>::getABarrierNode(lbl)
|
||||
node = DataFlow::MakeStateBarrierGuard<FlowState, BarrierGuard>::getABarrierNode(state)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,10 +264,10 @@ private class PropertyPresenceCheck extends BarrierGuard, DataFlow::ValueNode {
|
||||
not isPropertyPresentOnObjectPrototype(astNode.getPropertyName())
|
||||
}
|
||||
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState label) {
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
|
||||
e = astNode.getBase() and
|
||||
outcome = true and
|
||||
label = FlowState::objectPrototype()
|
||||
state = FlowState::objectPrototype()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,10 +279,10 @@ private class InExprCheck extends BarrierGuard, DataFlow::ValueNode {
|
||||
not isPropertyPresentOnObjectPrototype(astNode.getLeftOperand().getStringValue())
|
||||
}
|
||||
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState label) {
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
|
||||
e = astNode.getRightOperand() and
|
||||
outcome = true and
|
||||
label = FlowState::objectPrototype()
|
||||
state = FlowState::objectPrototype()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,10 +290,10 @@ private class InExprCheck extends BarrierGuard, DataFlow::ValueNode {
|
||||
private class InstanceofCheck extends BarrierGuard, DataFlow::ValueNode {
|
||||
override InstanceofExpr astNode;
|
||||
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState label) {
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
|
||||
e = astNode.getLeftOperand() and
|
||||
outcome = true and
|
||||
label = FlowState::objectPrototype()
|
||||
state = FlowState::objectPrototype()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,10 +311,10 @@ private class TypeofCheck extends BarrierGuard, DataFlow::ValueNode {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState label) {
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
|
||||
polarity = outcome and
|
||||
e = operand and
|
||||
label = FlowState::objectPrototype()
|
||||
state = FlowState::objectPrototype()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,10 +332,10 @@ class NumberGuard extends BarrierGuard instanceof DataFlow::CallNode {
|
||||
private class IsArrayCheck extends BarrierGuard, DataFlow::CallNode {
|
||||
IsArrayCheck() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") }
|
||||
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState label) {
|
||||
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
|
||||
e = this.getArgument(0).asExpr() and
|
||||
outcome = true and
|
||||
label = FlowState::objectPrototype()
|
||||
state = FlowState::objectPrototype()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ module PrototypePollutionConfig implements DataFlow::StateConfigSig {
|
||||
predicate isSink(DataFlow::Node node, FlowState state) { node.(Sink).getAFlowState() = state }
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node src, FlowState inlbl, DataFlow::Node dst, FlowState outlbl
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
TaintedObject::isAdditionalFlowStep(src, inlbl, dst, outlbl)
|
||||
TaintedObject::isAdditionalFlowStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet contents) {
|
||||
|
||||
@@ -23,8 +23,8 @@ module RequestForgeryConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) { sanitizingPrefixEdge(node, _) }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
isAdditionalRequestForgeryStep(pred, succ)
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalRequestForgeryStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ module ResourceExhaustionConfig implements DataFlow::ConfigSig {
|
||||
node = DataFlow::MakeBarrierGuard<BarrierGuard>::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node dst) {
|
||||
isNumericFlowStep(src, dst)
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isNumericFlowStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,15 +37,15 @@ module SecondOrderCommandInjectionConfig implements DataFlow::StateConfigSig {
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node src, FlowState inlbl, DataFlow::Node trg, FlowState outlbl
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
TaintedObject::isAdditionalFlowStep(src, inlbl, trg, outlbl)
|
||||
TaintedObject::isAdditionalFlowStep(node1, state1, node2, state2)
|
||||
or
|
||||
// We're not using a taint-tracking config because taint steps would then apply to all flow states.
|
||||
// So we use a plain data flow config and manually add the default taint steps.
|
||||
inlbl.isTaint() and
|
||||
TaintTracking::defaultTaintStep(src, trg) and
|
||||
inlbl = outlbl
|
||||
state1.isTaint() and
|
||||
TaintTracking::defaultTaintStep(node1, node2) and
|
||||
state1 = state2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@ module ServerSideUrlRedirectConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) { hostnameSanitizingPrefixEdge(node, _) }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(HtmlSanitizerCall call |
|
||||
pred = call.getInput() and
|
||||
succ = call
|
||||
node1 = call.getInput() and
|
||||
node2 = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,15 @@ module SqlInjectionConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(LdapJS::TaintPreservingLdapFilterStep filter |
|
||||
pred = filter.getInput() and
|
||||
succ = filter.getOutput()
|
||||
node1 = filter.getInput() and
|
||||
node2 = filter.getOutput()
|
||||
)
|
||||
or
|
||||
exists(HtmlSanitizerCall call |
|
||||
pred = call.getInput() and
|
||||
succ = call
|
||||
node1 = call.getInput() and
|
||||
node2 = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,15 +35,15 @@ module TemplateObjectInjectionConfig implements DataFlow::StateConfigSig {
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node src, FlowState inlbl, DataFlow::Node trg, FlowState outlbl
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
TaintedObject::isAdditionalFlowStep(src, inlbl, trg, outlbl)
|
||||
TaintedObject::isAdditionalFlowStep(node1, state1, node2, state2)
|
||||
or
|
||||
// We're not using a taint-tracking config because taint steps would then apply to all flow states.
|
||||
// So we use a plain data flow config and manually add the default taint steps.
|
||||
inlbl.isTaint() and
|
||||
TaintTracking::defaultTaintStep(src, trg) and
|
||||
inlbl = outlbl
|
||||
state1.isTaint() and
|
||||
TaintTracking::defaultTaintStep(node1, node2) and
|
||||
state1 = state2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ module UnsafeCodeConstruction {
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof CodeInjection::Sanitizer }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// HTML sanitizers are insufficient protection against code injection
|
||||
src = trg.(HtmlSanitizerCall).getInput()
|
||||
node1 = node2.(HtmlSanitizerCall).getInput()
|
||||
or
|
||||
none()
|
||||
// TODO: localFieldStep is too expensive with dataflow2
|
||||
|
||||
@@ -24,11 +24,11 @@ deprecated private class ConcreteUnsafeFunction extends UnsafeFunction {
|
||||
module UnsafeDynamicMethodAccessConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = UnsafeDynamicMethodAccess::FlowState;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState label) {
|
||||
source.(Source).getAFlowState() = label
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
source.(Source).getAFlowState() = state
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState label) { sink.(Sink).getAFlowState() = label }
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) { sink.(Sink).getAFlowState() = state }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node instanceof Sanitizer
|
||||
@@ -37,44 +37,44 @@ module UnsafeDynamicMethodAccessConfig implements DataFlow::StateConfigSig {
|
||||
not StringConcatenation::isCoercion(node)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState label) {
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) {
|
||||
TaintTracking::defaultSanitizer(node) and
|
||||
label = FlowState::taint()
|
||||
state = FlowState::taint()
|
||||
}
|
||||
|
||||
/** An additional flow step for use in both this configuration and the legacy configuration. */
|
||||
additional predicate additionalFlowStep(
|
||||
DataFlow::Node src, FlowState srclabel, DataFlow::Node dst, FlowState dstlabel
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
// Reading a property of the global object or of a function
|
||||
exists(DataFlow::PropRead read |
|
||||
PropertyInjection::hasUnsafeMethods(read.getBase().getALocalSource()) and
|
||||
src = read.getPropertyNameExpr().flow() and
|
||||
dst = read and
|
||||
srclabel = FlowState::taint() and
|
||||
dstlabel = FlowState::unsafeFunction()
|
||||
node1 = read.getPropertyNameExpr().flow() and
|
||||
node2 = read and
|
||||
state1 = FlowState::taint() and
|
||||
state2 = FlowState::unsafeFunction()
|
||||
)
|
||||
or
|
||||
// Reading a chain of properties from any object with a prototype can lead to Function
|
||||
exists(PropertyProjection proj |
|
||||
not PropertyInjection::isPrototypeLessObject(proj.getObject().getALocalSource()) and
|
||||
src = proj.getASelector() and
|
||||
dst = proj and
|
||||
srclabel = FlowState::taint() and
|
||||
dstlabel = FlowState::unsafeFunction()
|
||||
node1 = proj.getASelector() and
|
||||
node2 = proj and
|
||||
state1 = FlowState::taint() and
|
||||
state2 = FlowState::unsafeFunction()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node src, FlowState srclabel, DataFlow::Node dst, FlowState dstlabel
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
additionalFlowStep(src, srclabel, dst, dstlabel)
|
||||
additionalFlowStep(node1, state1, node2, state2)
|
||||
or
|
||||
// We're not using a taint-tracking config because taint steps would then apply to all flow states.
|
||||
// So we use a plain data flow config and manually add the default taint steps.
|
||||
srclabel = FlowState::taint() and
|
||||
TaintTracking::defaultTaintStep(src, dst) and
|
||||
srclabel = dstlabel
|
||||
state1 = FlowState::taint() and
|
||||
TaintTracking::defaultTaintStep(node1, node2) and
|
||||
state1 = state2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ module UnsafeHtmlConstructionConfig implements DataFlow::StateConfigSig {
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node pred, FlowState inlbl, DataFlow::Node succ, FlowState outlbl
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
// TODO: localFieldStep is too expensive with dataflow2
|
||||
// DataFlow::localFieldStep(pred, succ) and
|
||||
@@ -53,16 +53,16 @@ module UnsafeHtmlConstructionConfig implements DataFlow::StateConfigSig {
|
||||
// outlbl.isTaint()
|
||||
none()
|
||||
or
|
||||
TaintedObject::isAdditionalFlowStep(pred, inlbl, succ, outlbl)
|
||||
TaintedObject::isAdditionalFlowStep(node1, state1, node2, state2)
|
||||
or
|
||||
// property read from a tainted object is considered tainted
|
||||
succ.(DataFlow::PropRead).getBase() = pred and
|
||||
inlbl.isTaintedObject() and
|
||||
outlbl.isTaint()
|
||||
node2.(DataFlow::PropRead).getBase() = node1 and
|
||||
state1.isTaintedObject() and
|
||||
state2.isTaint()
|
||||
or
|
||||
TaintTracking::defaultTaintStep(pred, succ) and
|
||||
inlbl.isTaint() and
|
||||
outlbl = inlbl
|
||||
TaintTracking::defaultTaintStep(node1, node2) and
|
||||
state1.isTaint() and
|
||||
state2 = state1
|
||||
}
|
||||
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
|
||||
|
||||
@@ -22,13 +22,13 @@ module UnsafeJQueryPluginConfig implements DataFlow::ConfigSig {
|
||||
node = DataFlow::MakeBarrierGuard<BarrierGuard>::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node sink) {
|
||||
// jQuery plugins tend to be implemented as classes that store data in fields initialized by the constructor.
|
||||
// TODO: localFieldStep is too expensive with dataflow2
|
||||
// DataFlow::localFieldStep(pred, succ)
|
||||
none()
|
||||
or
|
||||
aliasPropertyPresenceStep(src, sink)
|
||||
aliasPropertyPresenceStep(node1, sink)
|
||||
}
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) {
|
||||
|
||||
@@ -26,7 +26,7 @@ module UnsafeShellCommandConstructionConfig implements DataFlow::ConfigSig {
|
||||
node = TaintTracking::AdHocWhitelistCheckSanitizer::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
none()
|
||||
// TODO: localFieldStep is too expensive with dataflow2
|
||||
// DataFlow::localFieldStep(pred, succ)
|
||||
|
||||
@@ -30,19 +30,19 @@ deprecated private class ConcreteMaybeFromProto extends MaybeFromProto {
|
||||
module UnvalidatedDynamicMethodCallConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = UnvalidatedDynamicMethodCall::FlowState;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState label) {
|
||||
source.(Source).getAFlowState() = label
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
source.(Source).getAFlowState() = state
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState label) { sink.(Sink).getAFlowState() = label }
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) { sink.(Sink).getAFlowState() = state }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState label) {
|
||||
node.(Sanitizer).getAFlowState() = label
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) {
|
||||
node.(Sanitizer).getAFlowState() = state
|
||||
or
|
||||
TaintTracking::defaultSanitizer(node) and
|
||||
label = FlowState::taint()
|
||||
state = FlowState::taint()
|
||||
or
|
||||
node = DataFlow::MakeStateBarrierGuard<FlowState, BarrierGuard>::getABarrierNode(label)
|
||||
node = DataFlow::MakeStateBarrierGuard<FlowState, BarrierGuard>::getABarrierNode(state)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
@@ -50,33 +50,33 @@ module UnvalidatedDynamicMethodCallConfig implements DataFlow::StateConfigSig {
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node src, FlowState srclabel, DataFlow::Node dst, FlowState dstlabel
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
exists(DataFlow::PropRead read |
|
||||
src = read.getPropertyNameExpr().flow() and
|
||||
dst = read and
|
||||
srclabel = FlowState::taint() and
|
||||
node1 = read.getPropertyNameExpr().flow() and
|
||||
node2 = read and
|
||||
state1 = FlowState::taint() and
|
||||
(
|
||||
dstlabel = FlowState::maybeNonFunction()
|
||||
state2 = FlowState::maybeNonFunction()
|
||||
or
|
||||
// a property of `Object.create(null)` cannot come from a prototype
|
||||
not PropertyInjection::isPrototypeLessObject(read.getBase().getALocalSource()) and
|
||||
dstlabel = FlowState::maybeFromProto()
|
||||
state2 = FlowState::maybeFromProto()
|
||||
) and
|
||||
// avoid overlapping results with unsafe dynamic method access query
|
||||
not PropertyInjection::hasUnsafeMethods(read.getBase().getALocalSource())
|
||||
)
|
||||
or
|
||||
exists(DataFlow::SourceNode base, DataFlow::CallNode get | get = base.getAMethodCall("get") |
|
||||
src = get.getArgument(0) and
|
||||
dst = get
|
||||
node1 = get.getArgument(0) and
|
||||
node2 = get
|
||||
) and
|
||||
srclabel = FlowState::taint() and
|
||||
dstlabel = FlowState::maybeNonFunction()
|
||||
state1 = FlowState::taint() and
|
||||
state2 = FlowState::maybeNonFunction()
|
||||
or
|
||||
srclabel = FlowState::taint() and
|
||||
TaintTracking::defaultTaintStep(src, dst) and
|
||||
srclabel = dstlabel
|
||||
state1 = FlowState::taint() and
|
||||
TaintTracking::defaultTaintStep(node1, node2) and
|
||||
state1 = state2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ module XssThroughDomConfig implements DataFlow::ConfigSig {
|
||||
node = Shared::BarrierGuard::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
succ = DataFlow::globalVarRef("URL").getAMemberCall("createObjectURL") and
|
||||
pred = succ.(DataFlow::InvokeNode).getArgument(0)
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
node2 = DataFlow::globalVarRef("URL").getAMemberCall("createObjectURL") and
|
||||
node1 = node2.(DataFlow::InvokeNode).getArgument(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ module PolynomialReDoSConfig implements DataFlow::ConfigSig {
|
||||
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
none()
|
||||
// TODO: localFieldStep is too expensive with dataflow2
|
||||
// DataFlow::localFieldStep(pred, succ)
|
||||
|
||||
@@ -65,27 +65,27 @@ module CodeInjectionConfig implements DataFlow::StateConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState label) {
|
||||
source instanceof ActiveThreatModelSource and label = TTaint()
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
source instanceof ActiveThreatModelSource and state = TTaint()
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof DynamicImport }
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState label) {
|
||||
sink instanceof WorkerThreads and label = TUrlConstructor()
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
sink instanceof WorkerThreads and state = TUrlConstructor()
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Barrier }
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node pred, FlowState predlbl, DataFlow::Node succ, FlowState succlbl
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
exists(DataFlow::NewNode newUrl | succ = newUrl |
|
||||
exists(DataFlow::NewNode newUrl | node2 = newUrl |
|
||||
newUrl = DataFlow::globalVarRef("URL").getAnInstantiation() and
|
||||
pred = newUrl.getArgument(0)
|
||||
node1 = newUrl.getArgument(0)
|
||||
) and
|
||||
predlbl = TTaint() and
|
||||
succlbl = TUrlConstructor()
|
||||
state1 = TTaint() and
|
||||
state2 = TUrlConstructor()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,15 @@ module EnvValueAndKeyInjectionConfig implements DataFlow::ConfigSig {
|
||||
sink = valueOfEnv()
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(DataFlow::InvokeNode ikn |
|
||||
ikn = DataFlow::globalVarRef("Object").getAMemberInvocation("keys")
|
||||
|
|
||||
pred = ikn.getArgument(0) and
|
||||
node1 = ikn.getArgument(0) and
|
||||
(
|
||||
succ = ikn.getAChainedMethodCall(["filter", "map"]) or
|
||||
succ = ikn or
|
||||
succ = ikn.getAChainedMethodCall("forEach").getABoundCallbackParameter(0, 0)
|
||||
node2 = ikn.getAChainedMethodCall(["filter", "map"]) or
|
||||
node2 = ikn or
|
||||
node2 = ikn.getAChainedMethodCall("forEach").getABoundCallbackParameter(0, 0)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ module DecompressionBombConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof DecompressionBomb::Sink }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(DecompressionBomb::AdditionalTaintStep addstep |
|
||||
addstep.isAdditionalTaintStep(pred, succ)
|
||||
addstep.isAdditionalTaintStep(node1, node2)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user