mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
JS: Do the same for additional taint steps
This commit is contained in:
@@ -1,6 +1,28 @@
|
||||
/**
|
||||
* Note: The contents of this file are exposed with the `TaintTracking::` prefix, via an import in `TaintTracking.qll`.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.internal.CachedStages
|
||||
|
||||
/**
|
||||
* A taint-propagating data flow edge that should be added to all taint tracking
|
||||
* configurations, but only those that use the new data flow library.
|
||||
*
|
||||
* This class is a singleton, and thus subclasses do not need to specify a characteristic predicate.
|
||||
*
|
||||
* Note: For performance reasons, all subclasses of this class should be part
|
||||
* of the standard library. Override `Configuration::isAdditionalTaintStep`
|
||||
* for analysis-specific taint steps.
|
||||
*/
|
||||
class AdditionalTaintStep extends Unit {
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge.
|
||||
*/
|
||||
predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-propagating data flow edge that should be added to all taint tracking
|
||||
* configurations in addition to standard data flow edges.
|
||||
@@ -102,6 +124,106 @@ class SharedTaintStep extends Unit {
|
||||
predicate promiseStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-propagating data flow edge that should be used with the old data flow library.
|
||||
*
|
||||
* This class is a singleton, and thus subclasses do not need to specify a characteristic predicate.
|
||||
*
|
||||
* Note: For performance reasons, all subclasses of this class should be part
|
||||
* of the standard library. Override `Configuration::isAdditionalTaintStep`
|
||||
* for analysis-specific taint steps.
|
||||
*
|
||||
* This class has multiple kinds of `step` predicates; these all have the same
|
||||
* effect on taint-tracking configurations. However, the categorization of steps
|
||||
* allows some data-flow configurations to opt in to specific kinds of taint steps.
|
||||
*/
|
||||
class LegacyTaintStep extends Unit {
|
||||
// Each step relation in this class should have a cached version in the `Cached` module
|
||||
// and be included in the `sharedTaintStep` predicate.
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge.
|
||||
*/
|
||||
predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through URI manipulation.
|
||||
*
|
||||
* Does not include string operations that aren't specific to URIs, such
|
||||
* as concatenation and substring operations.
|
||||
*/
|
||||
predicate uriStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge contributed by the heuristics library.
|
||||
*
|
||||
* Such steps are provided by the `semmle.javascript.heuristics` libraries
|
||||
* and will default to be being empty if those libraries are not imported.
|
||||
*/
|
||||
predicate heuristicStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through persistent storage.
|
||||
*/
|
||||
predicate persistentStorageStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through the heap.
|
||||
*/
|
||||
predicate heapStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through arrays.
|
||||
*
|
||||
* These steps considers an array to be tainted if it contains tainted elements.
|
||||
*/
|
||||
predicate arrayStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through the `state` or `props` or a React component.
|
||||
*/
|
||||
predicate viewComponentStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through string concatenation.
|
||||
*/
|
||||
predicate stringConcatenationStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through string manipulation (other than concatenation).
|
||||
*/
|
||||
predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through data serialization, such as `JSON.stringify`.
|
||||
*/
|
||||
predicate serializeStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through data deserialization, such as `JSON.parse`.
|
||||
*/
|
||||
predicate deserializeStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` → `succ` should be considered a taint-propagating
|
||||
* data flow edge through a promise.
|
||||
*
|
||||
* These steps consider a promise object to tainted if it can resolve to
|
||||
* a tainted value.
|
||||
*/
|
||||
predicate promiseStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Module existing only to ensure all taint steps are cached as a single stage,
|
||||
* and without the the `Unit` type column.
|
||||
@@ -110,6 +232,7 @@ cached
|
||||
private module Cached {
|
||||
cached
|
||||
predicate forceStage() {
|
||||
// TODO: ensure that this stage is only evaluated if using the old data flow library
|
||||
Stages::Taint::ref()
|
||||
}
|
||||
|
||||
@@ -120,6 +243,8 @@ private module Cached {
|
||||
cached
|
||||
predicate genericStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).step(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).step(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,6 +254,8 @@ private module Cached {
|
||||
cached
|
||||
predicate heuristicStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).heuristicStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).heuristicStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,6 +270,8 @@ private module Cached {
|
||||
cached
|
||||
predicate uriStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).uriStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).uriStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,6 +280,8 @@ private module Cached {
|
||||
cached
|
||||
predicate persistentStorageStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).persistentStorageStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).persistentStorageStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,6 +290,8 @@ private module Cached {
|
||||
cached
|
||||
predicate heapStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).heapStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).heapStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,6 +300,8 @@ private module Cached {
|
||||
cached
|
||||
predicate arrayStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).arrayStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).arrayStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,6 +311,8 @@ private module Cached {
|
||||
cached
|
||||
predicate viewComponentStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).viewComponentStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).viewComponentStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,6 +322,8 @@ private module Cached {
|
||||
cached
|
||||
predicate stringConcatenationStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).stringConcatenationStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).stringConcatenationStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,6 +333,8 @@ private module Cached {
|
||||
cached
|
||||
predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).stringManipulationStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).stringManipulationStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,6 +344,8 @@ private module Cached {
|
||||
cached
|
||||
predicate serializeStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).serializeStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).serializeStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,6 +355,8 @@ private module Cached {
|
||||
cached
|
||||
predicate deserializeStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).deserializeStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).deserializeStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,6 +369,8 @@ private module Cached {
|
||||
cached
|
||||
predicate promiseStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(SharedTaintStep step).promiseStep(pred, succ)
|
||||
or
|
||||
any(LegacyTaintStep step).promiseStep(pred, succ)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,6 +380,8 @@ import Cached::Public
|
||||
/**
|
||||
* Holds if `pred -> succ` is an edge used by all taint-tracking configurations in
|
||||
* the old data flow library.
|
||||
*
|
||||
* The new data flow library uses a different set of steps, exposed by `AdditionalTaintStep::step`.
|
||||
*/
|
||||
predicate sharedTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
Cached::genericStep(pred, succ) or
|
||||
@@ -248,3 +397,30 @@ predicate sharedTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
deserializeStep(pred, succ) or
|
||||
promiseStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains predicates for accessing the taint steps used by taint-tracking configurations
|
||||
* in the new data flow library.
|
||||
*/
|
||||
module AdditionalTaintStep {
|
||||
/**
|
||||
* Holds if `pred` → `succ` is considered a taint-propagating data flow edge when
|
||||
* using the new data flow library.
|
||||
*/
|
||||
cached
|
||||
predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(AdditionalTaintStep step).step(pred, succ) or
|
||||
any(SharedTaintStep step).step(pred, succ) or
|
||||
any(SharedTaintStep step).heuristicStep(pred, succ) or
|
||||
any(SharedTaintStep step).uriStep(pred, succ) or
|
||||
any(SharedTaintStep step).persistentStorageStep(pred, succ) or
|
||||
any(SharedTaintStep step).heapStep(pred, succ) or
|
||||
any(SharedTaintStep step).arrayStep(pred, succ) or
|
||||
any(SharedTaintStep step).viewComponentStep(pred, succ) or
|
||||
any(SharedTaintStep step).stringConcatenationStep(pred, succ) or
|
||||
any(SharedTaintStep step).stringManipulationStep(pred, succ) or
|
||||
any(SharedTaintStep step).serializeStep(pred, succ) or
|
||||
any(SharedTaintStep step).deserializeStep(pred, succ) or
|
||||
any(SharedTaintStep step).promiseStep(pred, succ)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ private import semmle.javascript.dataflow.internal.sharedlib.FlowSummaryImpl as
|
||||
|
||||
cached
|
||||
predicate defaultAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
TaintTracking::AdditionalTaintStep::step(node1, node2)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
|
||||
node2.(FlowSummaryNode).getSummaryNode(), false)
|
||||
or
|
||||
|
||||
Reference in New Issue
Block a user