mirror of
https://github.com/github/codeql.git
synced 2026-04-24 00:05:14 +02:00
JS: Migrate PrototypePollutingMergeCall
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user