JS: Mass rename to node1,state1,node2,state2 naming convention

This commit is contained in:
Asger F
2024-12-13 14:57:05 +01:00
parent ac6da6c2b1
commit 079294e55f
34 changed files with 220 additions and 218 deletions

View File

@@ -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) {

View File

@@ -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
)
}
}

View File

@@ -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) {

View File

@@ -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*())

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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))
}
}

View File

@@ -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)
}
}

View File

@@ -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()
)
}
}

View File

@@ -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 }

View File

@@ -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 }

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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()
}
}

View File

@@ -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) {

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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
}
}

View File

@@ -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
)
}
}

View File

@@ -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
)
}
}

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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 }

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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
}
}

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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()
}
}

View File

@@ -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)
)
)
}

View File

@@ -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)
)
}
}