-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Comments
Hi @DSimsek000 thanks a lot for raising this to our attention! I will forward it to our internal team working on javascript analysis. |
Hi 👋 The query |
Hi @asgerf , |
In this case you're probably better off making a copy of For example, the query would look like this: /** @kind path-problem */
import javascript
import semmle.javascript.security.dataflow.PrototypePollutingAssignmentQuery
import PrototypePollutingAssignmentFlow::PathGraph
class MyCustomSource extends Source {
MyCustomSource() {
this = /* ... */
}
override string describe() { result = "custom source" }
}
from
PrototypePollutingAssignmentFlow::PathNode source, PrototypePollutingAssignmentFlow::PathNode sink
where
PrototypePollutingAssignmentFlow::flowPath(source, sink) and
not isIgnoredLibraryFlow(source.getNode(), sink.getNode())
select sink, source, sink,
"This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@.",
source.getNode(), source.getNode().(Source).describe() |
Thank you asgerf! Using the above query I was able to find the vulnerability. However I still had to add the following taint step predicate for the class TStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
exists(CallExpr ca |
ca.getCalleeName() = "keys" and
ca = nodeTo.asExpr() and
ca.getAnArgument() = nodeFrom.asExpr()
)
}
} It seems Was this a deliberate design choice? |
Hi @asgerf, I was testing the above config against a few CVEs and encountered an issue related to calls to function set(input, value) {
let config = {};
let name = input.split(".");
let length = name.length;
name.forEach((item, index) => {
if (index === length - 1) {
config[item] = value;
} else {
config = config[item];
}
});
return config;
}
function set2(input, value) {
let config = {};
let name = input.split(".");
let length = name.length;
for (const item of name) {
if (item === name[length - 1]) {
config[item] = value;
} else {
config = config[item];
}
}
return config;
} I changed the sink predicate to The working taint path for the 1. for (const *item* of name) {
2. if (item === name[length - 1]) {
3. config[item] = value
4. } else {
5. config = config[item]
6. }
7. } 1. for (const item of name) {
2. if (item === name[length - 1]) {
3. config[item] = value
4. } else {
5. config = config[*item*]
6. }
7. } 1. for (const item of name) {
2. if (item === name[length - 1]) {
3. config[item] = value
4. } else {
5. config = *config[item]* // this should set the label to `FlowState::objectPrototype`
6. }
7. } 1. for (const item of name) {
2. if (item === name[length - 1]) {
3. config[item] = value
4. } else {
5. *config = config[item]*
6. }
7. } And now it goes back to the loop start and flags the sink: 1. for (const item of name) {
2. if (item === name[length - 1]) {
3. *config*[item] = value
4. } else {
5. config = config[item]
6. }
7. } I suspect it relates to codeql not covering the last step. Here the full query: /**
* @kind path-problem
*/
import javascript
import semmle.javascript.security.dataflow.PrototypePollutingAssignmentQuery
import PrototypePollutingAssignmentFlow::PathGraph
class MyCustomSource extends Source {
MyCustomSource() {
exists(Function f |
f.getName() = "set" and
this.asExpr().getEnclosingFunction() = f
|
this.asExpr() = f.getAParameter()
)
}
override string describe() { result = "custom source" }
}
from
PrototypePollutingAssignmentFlow::PathNode source, PrototypePollutingAssignmentFlow::PathNode sink
where
PrototypePollutingAssignmentFlow::flowPath(source, sink) and
not isIgnoredLibraryFlow(source.getNode(), sink.getNode())
select sink, source, sink,
"This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@.",
source.getNode(), source.getNode().(Source).describe() |
Hi,
I would like to report a possible false negative for SNYK-JS-XASSIGN-1759314.
Relevant code:
I ran the following query:
By providing the following additional taint steps, I managed to find the vulnerability (though this may be overly broad):
The text was updated successfully, but these errors were encountered: