Skip to content

codeql js taint tracking - write "recursive" additional taint step #19098

Open
@DSimsek000

Description

@DSimsek000

I have the following code:

function source() {
    fn0();
    fn1();
}

function fn0() {
    const a = process.env.SECRET;
    sink(a);
}

function fn1() {
    fn0();
}

In this example everything coming from the env is tainted. However, I do not want to find a taint path that starts at fn0 (where we have the env propread), but from source.

I came up with the following config that uses isAdditionalFlowStep to check whether the current function has a call to a function where an env propread is made:

module Config implements DataFlow::ConfigSig {
  predicate isSource(DataFlow::Node source) {
    exists(Function f |
      f.getName() = "source" and
      (
        source.asExpr() = f.getAParameter()
        or
        source.(DataFlow::FunctionNode).getFunction() = f
      )
    )
  }

  predicate isSink(DataFlow::Node node) {
    exists(DataFlow::CallNode cn |
      cn.getAnArgument() = node and
      cn.getCalleeName() = "sink"
    )
  }

  predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
    exists(DataFlow::FunctionNode fnEnv, DataFlow::PropRead propRead |
      propRead = toNode and
      propRead.getPropertyName() = "SECRET" and
      propRead.asExpr().getEnclosingFunction() = fnEnv.getFunction() and
      fromNode.(DataFlow::InvokeNode).getACallee() = fnEnv.getFunction()
    )
    or
    toNode.(DataFlow::InvokeNode).getEnclosingFunction() =
      fromNode.(DataFlow::FunctionNode).getFunction()
  }
}

This finds the taint path source -> fn0, but not source->fn1->fn0.
I am not sure how to restructure the predicate to introduce these taint steps in a recursive manner.

Metadata

Metadata

Assignees

Labels

javascriptPull requests that update Javascript codequestionFurther information is requested

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions