JS: Migrate PrototypePollutingMergeCall

This commit is contained in:
Asger F
2024-12-12 13:36:28 +01:00
parent c38e3a23eb
commit 355f7cdd54
2 changed files with 26 additions and 25 deletions

View File

@@ -9,7 +9,12 @@ import semmle.javascript.security.TaintedObject
import semmle.javascript.dependencies.SemVer
module PrototypePollution {
import semmle.javascript.security.CommonFlowState
/**
* DEPRECATED. This flow label is no longer in use, and there is no corresponding flow state, as
* the query instead relies on implicit reads at the sinks.
*
* A label for wrappers around tainted objects, that is, objects that are
* not completely user-controlled, but contain a user-controlled object.
*
@@ -23,12 +28,12 @@ module PrototypePollution {
* }
* ```
*/
abstract class TaintedObjectWrapper extends DataFlow::FlowLabel {
abstract deprecated class TaintedObjectWrapper extends DataFlow::FlowLabel {
TaintedObjectWrapper() { this = "tainted-object-wrapper" }
}
/** Companion module to the `TaintedObjectWrapper` class. */
module TaintedObjectWrapper {
/** DEPRECATED. Use `FlowState::taintedObjectWrapper()` instead. */
deprecated module TaintedObjectWrapper {
/** Gets the instance of the `TaintedObjectWrapper` label. */
TaintedObjectWrapper label() { any() }
}
@@ -40,7 +45,10 @@ module PrototypePollution {
/**
* Gets the type of data coming from this source.
*/
abstract DataFlow::FlowLabel getAFlowLabel();
FlowState getAFlowState() { result.isTaintedObject() }
/** DEPRECATED. Use `getAFlowState()` instead. */
deprecated DataFlow::FlowLabel getAFlowLabel() { result = this.getAFlowState().toFlowLabel() }
}
/**
@@ -50,7 +58,10 @@ module PrototypePollution {
/**
* Gets the type of data that can taint this sink.
*/
abstract DataFlow::FlowLabel getAFlowLabel();
FlowState getAFlowState() { result.isTaintedObject() }
/** DEPRECATED. Use `getAFlowState()` instead. */
deprecated DataFlow::FlowLabel getAFlowLabel() { result = this.getAFlowState().toFlowLabel() }
/**
* Holds if `moduleName` is the name of the module that defines this sink,
@@ -68,14 +79,14 @@ module PrototypePollution {
* in order to be flagged for prototype pollution.
*/
private class RemoteFlowAsSource extends Source instanceof RemoteFlowSource {
override DataFlow::FlowLabel getAFlowLabel() { result.isTaint() }
override FlowState getAFlowState() { result.isTaint() }
}
/**
* A source of user-controlled objects.
*/
private class TaintedObjectSource extends Source instanceof TaintedObject::Source {
override DataFlow::FlowLabel getAFlowLabel() { result = TaintedObject::label() }
override FlowState getAFlowState() { result.isTaintedObject() }
}
class DeepExtendSink extends Sink {
@@ -98,12 +109,6 @@ module PrototypePollution {
)
}
override DataFlow::FlowLabel getAFlowLabel() {
result = TaintedObject::label()
or
result = TaintedObjectWrapper::label()
}
override predicate dependencyInfo(string moduleName_, Locatable loc) {
moduleName = moduleName_ and
location = loc

View File

@@ -25,31 +25,27 @@ deprecated private class ConcreteTaintedObjectWrapper extends TaintedObjectWrapp
* leading to prototype pollution.
*/
module PrototypePollutionConfig implements DataFlow::StateConfigSig {
class FlowState = DataFlow::FlowLabel;
import semmle.javascript.security.CommonFlowState
predicate isSource(DataFlow::Node node, DataFlow::FlowLabel label) {
node.(Source).getAFlowLabel() = label
}
predicate isSource(DataFlow::Node node, FlowState state) { node.(Source).getAFlowState() = state }
predicate isSink(DataFlow::Node node, DataFlow::FlowLabel label) {
node.(Sink).getAFlowLabel() = label
}
predicate isSink(DataFlow::Node node, FlowState state) { node.(Sink).getAFlowState() = state }
predicate isAdditionalFlowStep(
DataFlow::Node src, DataFlow::FlowLabel inlbl, DataFlow::Node dst, DataFlow::FlowLabel outlbl
DataFlow::Node src, FlowState inlbl, DataFlow::Node dst, FlowState outlbl
) {
TaintedObject::step(src, dst, inlbl, outlbl)
TaintedObject::isAdditionalFlowStep(src, inlbl, dst, outlbl)
}
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet contents) {
// For recursive merge sinks, the deeply tainted object only needs to be reachable from the input, the input itself
// does not need to be deeply tainted.
isSink(node, TaintedObject::label()) and
isSink(node, FlowState::taintedObject()) and
contents = DataFlow::ContentSet::anyProperty()
}
predicate isBarrier(DataFlow::Node node, DataFlow::FlowLabel label) {
node = TaintedObject::SanitizerGuard::getABarrierNode(label)
predicate isBarrier(DataFlow::Node node, FlowState state) {
node = TaintedObject::SanitizerGuard::getABarrierNode(state)
}
}