Skip to content

Commit

Permalink
revert the JS deprecations. The old dataflow library is not that old yet
Browse files Browse the repository at this point in the history
  • Loading branch information
erik-krogh committed Jan 27, 2025
1 parent b6d636c commit fcd0f0e
Show file tree
Hide file tree
Showing 68 changed files with 1,647 additions and 1 deletion.
27 changes: 27 additions & 0 deletions javascript/ql/lib/semmle/javascript/ES2015Modules.qll
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ class ImportDeclaration extends Stmt, Import, @import_declaration {
*/
ObjectExpr getImportAttributes() { result = this.getChildExpr(-10) }

/**
* DEPRECATED: use `getImportAttributes` instead.
* Gets the object literal passed as part of the `with` (or `assert`) clause in this import declaration.
*
* For example, this gets the `{ type: "json" }` object literal in the following:
* ```js
* import foo from "foo" with { type: "json" };
* import foo from "foo" assert { type: "json" };
* ```
*/
deprecated ObjectExpr getImportAssertion() { result = this.getImportAttributes() }

/** Gets the `i`th import specifier of this import declaration. */
ImportSpecifier getSpecifier(int i) { result = this.getChildExpr(i) }

Expand Down Expand Up @@ -338,6 +350,21 @@ abstract class ExportDeclaration extends Stmt, @export_declaration {
* ```
*/
ObjectExpr getImportAttributes() { result = this.getChildExpr(-10) }

/**
* DEPRECATED: use `getImportAttributes` instead.
* Gets the object literal passed as part of the `with` (or `assert`) clause, if this is
* a re-export declaration.
*
* For example, this gets the `{ type: "json" }` expression in each of the following:
* ```js
* export { x } from 'foo' with { type: "json" };
* export * from 'foo' with { type: "json" };
* export * as x from 'foo' with { type: "json" };
* export * from 'foo' assert { type: "json" };
* ```
*/
deprecated ObjectExpr getImportAssertion() { result = this.getImportAttributes() }
}

/**
Expand Down
11 changes: 11 additions & 0 deletions javascript/ql/lib/semmle/javascript/Expr.qll
Original file line number Diff line number Diff line change
Expand Up @@ -2830,6 +2830,17 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import {
*/
Expr getImportOptions() { result = this.getChildExpr(1) }

/**
* DEPRECATED: use `getImportOptions` instead.
* Gets the second "argument" to the import expression, that is, the `Y` in `import(X, Y)`.
*
* For example, gets the `{ with: { type: "json" }}` expression in the following:
* ```js
* import('foo', { with: { type: "json" }})
* ```
*/
deprecated Expr getImportAttributes() { result = this.getImportOptions() }

override Module getEnclosingModule() { result = this.getTopLevel() }

override DataFlow::Node getImportedModuleNode() { result = DataFlow::valueNode(this) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,19 @@ module BrokenCryptoAlgorithmConfig implements DataFlow::ConfigSig {
* Taint tracking flow for sensitive information in broken or weak cryptographic algorithms.
*/
module BrokenCryptoAlgorithmFlow = TaintTracking::Global<BrokenCryptoAlgorithmConfig>;

/**
* DEPRECATED. Use the `BrokenCryptoAlgorithmFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "BrokenCryptoAlgorithm" }

override predicate isSource(DataFlow::Node source) { source instanceof Source }

override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }

override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node) or
node instanceof Sanitizer
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,24 @@ module BuildArtifactLeakConfig implements DataFlow::ConfigSig {
* Taint tracking flow for storage of sensitive information in build artifact.
*/
module BuildArtifactLeakFlow = TaintTracking::Global<BuildArtifactLeakConfig>;

/**
* DEPRECATED. Use the `BuildArtifactLeakFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "BuildArtifactLeak" }

override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) {
source.(CleartextLogging::Source).getLabel() = lbl
}

override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) {
sink.(Sink).getLabel() = lbl
}

override predicate isSanitizer(DataFlow::Node node) { node instanceof CleartextLogging::Barrier }

override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) {
CleartextLogging::isAdditionalTaintStep(src, trg)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,22 @@ module CleartextLogging {
abstract class Source extends DataFlow::Node {
/** Gets a string that describes the type of this data flow source. */
abstract string describe();

/**
* DEPRECATED. Overriding this predicate no longer has any effect.
*/
deprecated DataFlow::FlowLabel getLabel() { result.isTaint() }
}

/**
* A data flow sink for clear-text logging of sensitive information.
*/
abstract class Sink extends DataFlow::Node { }
abstract class Sink extends DataFlow::Node {
/**
* DEPRECATED. Overriding this predicate no longer has any effect.
*/
deprecated DataFlow::FlowLabel getLabel() { result.isTaint() }
}

/**
* A barrier for clear-text logging of sensitive information.
Expand Down Expand Up @@ -188,6 +198,15 @@ module CleartextLogging {
}
}

/**
* DEPRECATED. Use `Barrier` instead, sanitized have been replaced by sanitized nodes.
*
* Holds if the edge `pred` -> `succ` should be sanitized for clear-text logging of sensitive information.
*/
deprecated predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) {
succ.(DataFlow::PropRead).getBase() = pred
}

/**
* Holds if the edge `src` -> `trg` is an additional taint-step for clear-text logging of sensitive information.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,24 @@ module CleartextLoggingConfig implements DataFlow::ConfigSig {
* Taint tracking flow for clear-text logging of sensitive information.
*/
module CleartextLoggingFlow = TaintTracking::Global<CleartextLoggingConfig>;

/**
* DEPRECATED. Use the `CleartextLoggingFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CleartextLogging" }

override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) {
source.(Source).getLabel() = lbl
}

override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) {
sink.(Sink).getLabel() = lbl
}

override predicate isSanitizer(DataFlow::Node node) { node instanceof Barrier }

override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) {
CleartextLogging::isAdditionalTaintStep(src, trg)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,16 @@ module ClearTextStorageConfig implements DataFlow::ConfigSig {
}

module ClearTextStorageFlow = TaintTracking::Global<ClearTextStorageConfig>;

/**
* DEPRECATED. Use the `ClearTextStorageFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ClearTextStorage" }

override predicate isSource(DataFlow::Node source) { source instanceof Source }

override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }

override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,30 @@ module ClientSideRequestForgeryConfig implements DataFlow::ConfigSig {
* Taint tracking for client-side request forgery.
*/
module ClientSideRequestForgeryFlow = TaintTracking::Global<ClientSideRequestForgeryConfig>;

/**
* DEPRECATED. Use the `ClientSideRequestForgeryFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ClientSideRequestForgery" }

override predicate isSource(DataFlow::Node source) {
exists(Source src |
source = src and
not src.isServerSide()
)
}

override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }

override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node) or
node instanceof Sanitizer
}

override predicate isSanitizerOut(DataFlow::Node node) { sanitizingPrefixEdge(node, _) }

override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
isAdditionalRequestForgeryStep(pred, succ)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,48 @@ module ClientSideUrlRedirectConfig implements DataFlow::StateConfigSig {
* Taint-tracking flow for reasoning about unvalidated URL redirections.
*/
module ClientSideUrlRedirectFlow = TaintTracking::GlobalWithState<ClientSideUrlRedirectConfig>;

/**
* A taint-tracking configuration for reasoning about unvalidated URL redirections.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ClientSideUrlRedirect" }

override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) {
source.(Source).getAFlowLabel() = lbl
}

override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }

override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node) or
node instanceof Sanitizer
}

override predicate isSanitizerOut(DataFlow::Node node) { hostnameSanitizingPrefixEdge(node, _) }

override predicate isAdditionalFlowStep(
DataFlow::Node node1, DataFlow::Node node2, DataFlow::FlowLabel state1,
DataFlow::FlowLabel state2
) {
ClientSideUrlRedirectConfig::isAdditionalFlowStep(node1, FlowState::fromFlowLabel(state1),
node2, FlowState::fromFlowLabel(state2))
or
// Preserve document.url label in step from `location` to `location.href` or `location.toString()`
state1 instanceof DocumentUrl and
state2 instanceof DocumentUrl and
(
node2.(DataFlow::PropRead).accesses(node1, "href")
or
exists(DataFlow::CallNode call |
call.getCalleeName() = "toString" and
node1 = call.getReceiver() and
node2 = call
)
)
}

override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
guard instanceof HostnameSanitizerGuard
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,23 @@ module CodeInjectionConfig implements DataFlow::ConfigSig {
* Taint-tracking for reasoning about code injection vulnerabilities.
*/
module CodeInjectionFlow = TaintTracking::Global<CodeInjectionConfig>;

/**
* DEPRRECATED. Use the `CodeInjectionFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CodeInjection" }

override predicate isSource(DataFlow::Node source) { source instanceof Source }

override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }

override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node) or
node instanceof Sanitizer
}

override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
CodeInjectionConfig::isAdditionalFlowStep(node1, node2)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,16 @@ module CommandInjectionConfig implements DataFlow::ConfigSig {
* Taint-tracking for reasoning about command-injection vulnerabilities.
*/
module CommandInjectionFlow = TaintTracking::Global<CommandInjectionConfig>;

/**
* DEPRECATED. Use the `CommandInjectionFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CommandInjection" }

override predicate isSource(DataFlow::Node source) { CommandInjectionConfig::isSource(source) }

override predicate isSink(DataFlow::Node sink) { CommandInjectionConfig::isSink(sink) }

override predicate isSanitizer(DataFlow::Node node) { CommandInjectionConfig::isBarrier(node) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ module ConditionalBypassConfig implements DataFlow::ConfigSig {
*/
module ConditionalBypassFlow = TaintTracking::Global<ConditionalBypassConfig>;

/**
* DEPRECATED. Use the `ConditionalBypassFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ConditionalBypass" }

override predicate isSource(DataFlow::Node source) { source instanceof Source }

override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }

override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node) or
node instanceof Sanitizer
}

override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node dst) {
ConditionalBypassConfig::isAdditionalFlowStep(src, dst)
}
}

/**
* Holds if the value of `nd` flows into `guard`.
*/
Expand Down Expand Up @@ -129,3 +149,61 @@ predicate isEarlyAbortGuardNode(ConditionalBypassFlow::PathNode e, SensitiveActi
not action.asExpr().getEnclosingStmt().nestedIn(guard)
)
}

/**
* Holds if `sink` guards `action`, and `source` taints `sink`.
*
* If flow from `source` taints `sink`, then an attacker can
* control if `action` should be executed or not.
*/
deprecated predicate isTaintedGuardForSensitiveAction(
DataFlow::PathNode sink, DataFlow::PathNode source, SensitiveAction action
) {
action = sink.getNode().(Sink).getAction() and
// exclude the intermediary sink
not sink.getNode() instanceof SensitiveActionGuardComparisonOperand and
exists(Configuration cfg |
// ordinary taint tracking to a guard
cfg.hasFlowPath(source, sink)
or
// taint tracking to both operands of a guard comparison
exists(
SensitiveActionGuardComparison cmp, DataFlow::PathNode lSource, DataFlow::PathNode rSource,
DataFlow::PathNode lSink, DataFlow::PathNode rSink
|
sink.getNode() = cmp.getGuard() and
cfg.hasFlowPath(lSource, lSink) and
lSink.getNode() = DataFlow::valueNode(cmp.getLeftOperand()) and
cfg.hasFlowPath(rSource, rSink) and
rSink.getNode() = DataFlow::valueNode(cmp.getRightOperand())
|
source = lSource or
source = rSource
)
)
}

/**
* Holds if `e` effectively guards access to `action` by returning or throwing early.
*
* Example: `if (e) return; action(x)`.
*/
deprecated predicate isEarlyAbortGuard(DataFlow::PathNode e, SensitiveAction action) {
exists(IfStmt guard |
// `e` is in the condition of an if-statement ...
e.getNode().(Sink).asExpr().getParentExpr*() = guard.getCondition() and
// ... where the then-branch always throws or returns
exists(Stmt abort |
abort instanceof ThrowStmt or
abort instanceof ReturnStmt
|
abort.nestedIn(guard) and
abort.getBasicBlock().(ReachableBasicBlock).postDominates(guard.getThen().getBasicBlock())
) and
// ... and the else-branch does not exist
not exists(guard.getElse())
|
// ... and `action` is outside the if-statement
not action.asExpr().getEnclosingStmt().nestedIn(guard)
)
}
Loading

0 comments on commit fcd0f0e

Please sign in to comment.