Skip to content

codeql not tracking certian object literals #7421

@SZFsir

Description

@SZFsir

When I use taint tracking to test code below

function Compiler(source){
    this.pp = source.pretty;
    sink1(this.pp)
}

Compiler.prototype = {
    compile: function (){
        sink2(this.pp);
    }
}

function generateCode(source) {
    return new Compiler(source).compile();
}
var data = easySource();

generateCode({pretty: data.pretty})
/**
 * @name data-flow
 * @kind path-problem
 * @problem.severity warning
 * @tags security
 * @id js
 */

import javascript
import DataFlow::PathGraph

DataFlow::SourceNode easySourceTracker(DataFlow::TypeTracker t) {
    t.start() and
    result instanceof MyTestSource
    or
    exists(DataFlow::TypeTracker t2 | result = easySourceTracker(t2).track(t2, t))
}

class MyTestSource extends DataFlow::Node {
    MyTestSource(){
        exists(CallExpr call |
            call.getCalleeName()="easySource" | 
            this.asExpr() = call
        )
    }
}

class MyTestSink extends DataFlow::Node {
    MyTestSink(){
        exists(DataFlow::InvokeNode call | 
            call.getCalleeName().indexOf("sink") != -1 |
            this = call.getAnArgument()
        )
    }
} 


class TestConfiguration extends TaintTracking::Configuration {
    TestConfiguration() { this = "TestConfiguration" }

  override predicate isSource(DataFlow::Node source) {
    source = easySourceTracker(_)
  }

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

from TestConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::InvokeNode call
where cfg.hasFlowPath(source, sink)
and call.getAnArgument() = sink.getNode()
select sink.getNode(), source, sink, call.getCalleeName()

I found codeql can not find the taint flow to sink2(this.pp);
But if I modify generateCode({pretty: data.pretty}) to generateCode(data), codeql now can find sink2(this.pp);.

Although I found we could add localFieldStep to record all step from pred to succ through a field accessed through this in a class.

   override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
     DataFlow::localFieldStep(pred, succ)
   }

But I am confused, why can codeql handled this case after modify generateCode({pretty: data.pretty}) to generateCode(data) or why it can’t be handled before the modification.

Metadata

Metadata

Assignees

No one assigned

    Labels

    JSquestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions