Skip to content

JS: Allow MaD flow through properties #8670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,16 @@ private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
override string getSourceType() { result = "Remote flow" }
}

/**
* Like `ModelOutput::summaryStep` but with API nodes mapped to data-flow nodes.
*/
private predicate summaryStepNodes(DataFlow::Node pred, DataFlow::Node succ, string kind) {
exists(API::Node predNode, API::Node succNode |
Specific::summaryStep(predNode, succNode, kind) and
pred = predNode.getARhs() and
succ = succNode.getAnImmediateUse()
)
}

/** Data flow steps induced by summary models of kind `value`. */
private class DataFlowStepFromSummary extends DataFlow::SharedFlowStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
summaryStepNodes(pred, succ, "value")
Specific::summaryStep(pred, succ, "value")
}
}

/** Taint steps induced by summary models of kind `taint`. */
private class TaintStepFromSummary extends TaintTracking::SharedTaintStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
summaryStepNodes(pred, succ, "taint")
Specific::summaryStep(pred, succ, "taint")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ module ModelInput {
* indicates that for each call to `(package, type, path)`, the value referred to by `input`
* can flow to the value referred to by `output`.
*
* Alternatively, if `input` is the empty string and `output` consists of a single token,
* the value referred to by `(package, type, path)` may flow to the value referred to by `output`.
*
* `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps,
* respectively.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,15 +197,26 @@ private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPat
/**
* Holds if a CSV summary contributed the step `pred -> succ` of the given `kind`.
*/
predicate summaryStep(API::Node pred, API::Node succ, string kind) {
predicate summaryStep(DataFlow::Node pred, DataFlow::Node succ, string kind) {
exists(
string package, string type, string path, API::InvokeNode base, AccessPath input,
AccessPath output
|
ModelOutput::relevantSummaryModel(package, type, path, input, output, kind) and
ModelOutput::resolvedSummaryBase(package, type, path, base) and
pred = getNodeFromInputOutputPath(base, input) and
succ = getNodeFromInputOutputPath(base, output)
pred = getNodeFromInputOutputPath(base, input).getARhs() and
succ = getNodeFromInputOutputPath(base, output).getAnImmediateUse()
)
or
exists(
string package, string type, string path, API::Node base, AccessPath output,
DataFlow::PropRead read
|
ModelOutput::relevantSummaryModel(package, type, path, "", output, kind) and
base = getNodeFromPath(package, type, path) and
read = getSuccessorFromNode(base, output).getAnImmediateUse() and
pred = read.getBase() and
succ = read
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ taintFlow
| test.js:182:12:182:19 | source() | test.js:182:12:182:19 | source() |
| test.js:187:31:187:31 | x | test.js:189:10:189:10 | x |
| test.js:203:32:203:39 | source() | test.js:203:32:203:39 | source() |
| test.js:209:13:209:20 | source() | test.js:210:8:210:19 | obj.self.foo |
isSink
| test.js:54:18:54:25 | source() | test-sink |
| test.js:55:22:55:29 | source() | test-sink |
Expand Down
6 changes: 6 additions & 0 deletions javascript/ql/test/library-tests/frameworks/data/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,9 @@ class OtherClass {
this.accessorAroundField = source(); // NOT OK
}
}

function testFlowThroughProp() {
const obj = new testlib.Obj();
obj.foo = source();
sink(obj.self.foo); // NOT OK
}
1 change: 1 addition & 0 deletions javascript/ql/test/library-tests/frameworks/data/test.ql
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Steps extends ModelInput::SummaryModelCsv {
"testlib;;Member[preserveAllButFirstArgument];Argument[1..];ReturnValue;taint",
"testlib;;Member[preserveAllIfCall].Call;Argument[0..];ReturnValue;taint",
"testlib;;Member[getSource].ReturnValue.Member[continue];Argument[this];ReturnValue;taint",
"testlib;;Member[Obj].Instance;;Member[self];value",
]
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ module ModelInput {
* indicates that for each call to `(package, type, path)`, the value referred to by `input`
* can flow to the value referred to by `output`.
*
* Alternatively, if `input` is the empty string and `output` consists of a single token,
* the value referred to by `(package, type, path)` may flow to the value referred to by `output`.
*
* `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps,
* respectively.
*/
Expand Down