Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General issue - JavaScript data flow analysis #5177

Closed
gdemarcsek opened this issue Feb 15, 2021 · 4 comments
Closed

General issue - JavaScript data flow analysis #5177

gdemarcsek opened this issue Feb 15, 2021 · 4 comments
Assignees
Labels
JS question Further information is requested Stale

Comments

@gdemarcsek
Copy link

gdemarcsek commented Feb 15, 2021

Description of the issue
The following DOM XSS vector is recognized nicely (CWE-079):

function test() {
    let x = new URLSearchParams(location.search).get('x');
    document.getElementById("sink").innerHTML = x;
}

But this one is not recognized:

function test() {
    [document.getElementById("sink")][0].innerHTML = new URLSearchParams(location.search).get('x');
}

Is this a limitation of the JS data flow analysis library, generic limitation of the methodology or just an uncovered scenario (e.g. not propagating taint through array literals to their elements?)

My original test case was more complicated and a bit more realistic (like I could imagine similar code to be written IRL):

function f(e) {
    e.innerHTML = new URLSearchParams(location.search).get('x');
}
[document.getElementById("sink")].map(f);

But this didn't work so I started to simplify. Same for a forEach + arrow function.

@gdemarcsek gdemarcsek added the question Further information is requested label Feb 15, 2021
@hmakholm hmakholm added the JS label Feb 15, 2021
@hmakholm
Copy link
Contributor

@github/codeql-javascript might have some input here.

@erik-krogh
Copy link
Contributor

erik-krogh commented Feb 16, 2021

I would say it's an uncovered scenario.

In DOM.qll we track which values are DOM nodes.
We don't use the full featured data flow analysis to track these DOM nodes, we instead use a more lightweight approach we call type tracking.
Getting type-tracking to support your original test case would only require a small change to the ArrayCreationStep class.
Specifically, changing ArrayCreationStep to the below would support your original test case.

private class ArrayCreationStep extends PreCallGraphStep {
  override predicate storeStep(DataFlow::Node element, DataFlow::SourceNode obj, string prop) {
    exists(DataFlow::ArrayCreationNode arr, int i |
      element = arr.getElement(i) and
      obj = arr and
      if arr = any(PromiseAllCreation c).getArrayNode()
      then prop = arrayElement(i)
      else prop = arrayElement()
    )
  }
}

However, this might introduce false positives if an array contain elements of different types.

But it's something I think is worth investigating.

@github-actions
Copy link
Contributor

This issue is stale because it has been open 14 days with no activity. Comment or remove the stale label in order to avoid having this issue closed in 7 days.

@github-actions github-actions bot added the Stale label Apr 16, 2021
@erik-krogh
Copy link
Contributor

But it's something I think is worth investigating.

I've now merged the above suggestion as part of another PR.
So the scenario you describe is now supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JS question Further information is requested Stale
Projects
None yet
Development

No branches or pull requests

3 participants