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

CodeQL False Negative - Protototype Pollution #18665

Open
DSimsek000 opened this issue Feb 3, 2025 · 3 comments
Open

CodeQL False Negative - Protototype Pollution #18665

DSimsek000 opened this issue Feb 3, 2025 · 3 comments
Labels
question Further information is requested

Comments

@DSimsek000
Copy link

Hi,
I would like to report a possible false negative for SNYK-JS-XASSIGN-1759314.

Relevant code:

const XAssign = {
   assign: function (...args) {
      /**
       * Combine object properties or concat array properties
       *
       * @param {any} acc the target or accumulator
       * @param {any} obj object to apply
       */

      function apply(acc, obj) {
         if (obj == null || typeof obj !== "object") {
            return // ignore non-object args
         }
         Object.keys(obj)
            .forEach((key) => {
               const value = obj[key]
               if (Array.isArray(value)) {
                  acc[key] =
                  acc[key] && Array.isArray(acc[key])
                     ? acc[key].concat(value)
                     : value
               } else if (typeof value === "object") {
                  acc[key] = acc[key] || {}
                  if (Array.isArray(acc[key])) {
                     acc[key] = {} // getting overridden with an Object!
                     apply(acc[key], value)
                  } else if (typeof acc[key] === "object") {
                     apply(acc[key], value)
                  } else {
                     acc[key] = value
                  }
               } else {
                  acc[key] = value
               }
            })
      }

      /**
       * Apply merge for each object argument.
       */
      const result = {}
      args.forEach((obj) => apply(result, obj))
      return result
   },
}

I ran the following query:

/**
 * @name Prototype pollution
 * @description Using externally controlled input to set properties on the prototype of an object can lead to prototype pollution.
 * @severity high
 * @kind path-problem
 * @precision high
 * @id js/prototype-pollution
 * @tags external/cwe/cwe-471 external/cwe/cwe-915
 */

import javascript
import semmle.javascript.dataflow.TaintTracking
import semmle.javascript.security.dataflow.PrototypePollutingAssignmentCustomizations::PrototypePollutingAssignment

module Config implements DataFlow::ConfigSig {
  DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }

  predicate isSource(DataFlow::Node source) {
    exists(Function f | f.getName() = "assign" | source.asExpr() = f.getAParameter())
  }

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

module Flow = TaintTracking::Global<Config>;

import Flow::PathGraph

from Flow::PathNode source, Flow::PathNode sink
where Flow::flowPath(source, sink)
select sink.getNode(), source, sink, ""

By providing the following additional taint steps, I managed to find the vulnerability (though this may be overly broad):

predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
    exists(CallExpr ca | ca = toNode.asExpr() and ca.getAnArgument() = fromNode.asExpr())
    or
    exists(IndexExpr ie | ie = toNode.asExpr() and ie.getIndex() = fromNode.asExpr())
}
@DSimsek000 DSimsek000 added the question Further information is requested label Feb 3, 2025
@redsun82
Copy link
Contributor

redsun82 commented Feb 4, 2025

Hi @DSimsek000 thanks a lot for raising this to our attention! I will forward it to our internal team working on javascript analysis.

@asgerf
Copy link
Contributor

asgerf commented Feb 4, 2025

Hi 👋

The query js/prototype-pollution-utility (in this file) seems to flag this out of the box. Is there a reason you want a custom query for this?

@DSimsek000
Copy link
Author

Hi @asgerf ,
my goal was to analyse a specific entry point and do global taint analysis. I was under the assumption that the above query would import all prototype pollution sink definitions.

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

No branches or pull requests

3 participants