mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge branch 'main' into js/vue_tanstack_model
This commit is contained in:
4
javascript/ql/lib/change-notes/2025-03-13-unescape.md
Normal file
4
javascript/ql/lib/change-notes/2025-03-13-unescape.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added taint-steps for `unescape()`.
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import javascript
|
||||
private import dataflow.internal.StepSummary
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps
|
||||
|
||||
/**
|
||||
* A call to the `Promise` constructor, such as `new Promise((resolve, reject) => { ... })`.
|
||||
@@ -397,6 +398,17 @@ module PromiseFlow {
|
||||
value = call.getCallback(0).getExceptionalReturn() and
|
||||
obj = call
|
||||
)
|
||||
or
|
||||
exists(DataFlow::FunctionNode f | f.getFunction().isAsync() |
|
||||
// ordinary return
|
||||
prop = valueProp() and
|
||||
value = f.getAReturn() and
|
||||
obj = f.getReturnNode()
|
||||
or
|
||||
// exceptional return
|
||||
prop = errorProp() and
|
||||
localExceptionStepWithAsyncFlag(value, obj, true)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,30 +537,6 @@ private class PromiseTaintStep extends TaintTracking::LegacyTaintStep {
|
||||
* Defines flow steps for return on async functions.
|
||||
*/
|
||||
private module AsyncReturnSteps {
|
||||
private predicate valueProp = Promises::valueProp/0;
|
||||
|
||||
private predicate errorProp = Promises::errorProp/0;
|
||||
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps
|
||||
|
||||
/**
|
||||
* A data-flow step for ordinary and exceptional returns from async functions.
|
||||
*/
|
||||
private class AsyncReturn extends LegacyPreCallGraphStep {
|
||||
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
exists(DataFlow::FunctionNode f | f.getFunction().isAsync() |
|
||||
// ordinary return
|
||||
prop = valueProp() and
|
||||
pred = f.getAReturn() and
|
||||
succ = f.getReturnNode()
|
||||
or
|
||||
// exceptional return
|
||||
prop = errorProp() and
|
||||
localExceptionStepWithAsyncFlag(pred, succ, true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow step for ordinary return from an async function in a taint configuration.
|
||||
*/
|
||||
|
||||
@@ -494,7 +494,7 @@ module TaintTracking {
|
||||
succ = c and
|
||||
c =
|
||||
DataFlow::globalVarRef([
|
||||
"encodeURI", "decodeURI", "encodeURIComponent", "decodeURIComponent"
|
||||
"encodeURI", "decodeURI", "encodeURIComponent", "decodeURIComponent", "unescape"
|
||||
]).getACall() and
|
||||
pred = c.getArgument(0)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as t from "testlib";
|
||||
|
||||
async function getData1() {
|
||||
const data = await fetch("https://example.com/content");
|
||||
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
|
||||
}
|
||||
|
||||
export function use1() {
|
||||
t.foo(() => getData1());
|
||||
}
|
||||
|
||||
async function getData2() {
|
||||
const data = await fetch("https://example.com/content");
|
||||
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
|
||||
}
|
||||
|
||||
export function use2() {
|
||||
t.foo(getData2);
|
||||
}
|
||||
|
||||
export function use3() {
|
||||
t.foo(async () => {
|
||||
const data = await fetch("https://example.com/content");
|
||||
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
|
||||
});
|
||||
}
|
||||
@@ -223,6 +223,7 @@
|
||||
| tst.js:477:18:477:40 | locatio ... bstr(1) | tst.js:477:18:477:30 | location.hash | tst.js:477:18:477:40 | locatio ... bstr(1) | Cross-site scripting vulnerability due to $@. | tst.js:477:18:477:30 | location.hash | user-provided value |
|
||||
| tst.js:484:33:484:63 | decodeU ... n.hash) | tst.js:484:43:484:62 | window.location.hash | tst.js:484:33:484:63 | decodeU ... n.hash) | Cross-site scripting vulnerability due to $@. | tst.js:484:43:484:62 | window.location.hash | user-provided value |
|
||||
| tst.js:492:18:492:54 | target. ... "), '') | tst.js:491:16:491:39 | documen ... .search | tst.js:492:18:492:54 | target. ... "), '') | Cross-site scripting vulnerability due to $@. | tst.js:491:16:491:39 | documen ... .search | user-provided value |
|
||||
| tst.js:499:18:499:33 | unescape(source) | tst.js:498:16:498:26 | window.name | tst.js:499:18:499:33 | unescape(source) | Cross-site scripting vulnerability due to $@. | tst.js:498:16:498:26 | window.name | user-provided value |
|
||||
| typeahead.js:25:18:25:20 | val | typeahead.js:20:22:20:45 | documen ... .search | typeahead.js:25:18:25:20 | val | Cross-site scripting vulnerability due to $@. | typeahead.js:20:22:20:45 | documen ... .search | user-provided value |
|
||||
| v-html.vue:2:8:2:23 | v-html=tainted | v-html.vue:6:42:6:58 | document.location | v-html.vue:2:8:2:23 | v-html=tainted | Cross-site scripting vulnerability due to $@. | v-html.vue:6:42:6:58 | document.location | user-provided value |
|
||||
| various-concat-obfuscations.js:4:4:4:31 | "<div>" ... </div>" | various-concat-obfuscations.js:2:16:2:39 | documen ... .search | various-concat-obfuscations.js:4:4:4:31 | "<div>" ... </div>" | Cross-site scripting vulnerability due to $@. | various-concat-obfuscations.js:2:16:2:39 | documen ... .search | user-provided value |
|
||||
@@ -745,6 +746,9 @@ edges
|
||||
| tst.js:491:7:491:39 | target | tst.js:492:18:492:23 | target | provenance | |
|
||||
| tst.js:491:16:491:39 | documen ... .search | tst.js:491:7:491:39 | target | provenance | |
|
||||
| tst.js:492:18:492:23 | target | tst.js:492:18:492:54 | target. ... "), '') | provenance | |
|
||||
| tst.js:498:7:498:26 | source | tst.js:499:27:499:32 | source | provenance | |
|
||||
| tst.js:498:16:498:26 | window.name | tst.js:498:7:498:26 | source | provenance | |
|
||||
| tst.js:499:27:499:32 | source | tst.js:499:18:499:33 | unescape(source) | provenance | |
|
||||
| typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target | provenance | |
|
||||
| typeahead.js:20:22:20:45 | documen ... .search | typeahead.js:20:13:20:45 | target | provenance | |
|
||||
| typeahead.js:21:12:21:17 | target | typeahead.js:24:30:24:32 | val | provenance | |
|
||||
@@ -1397,6 +1401,10 @@ nodes
|
||||
| tst.js:491:16:491:39 | documen ... .search | semmle.label | documen ... .search |
|
||||
| tst.js:492:18:492:23 | target | semmle.label | target |
|
||||
| tst.js:492:18:492:54 | target. ... "), '') | semmle.label | target. ... "), '') |
|
||||
| tst.js:498:7:498:26 | source | semmle.label | source |
|
||||
| tst.js:498:16:498:26 | window.name | semmle.label | window.name |
|
||||
| tst.js:499:18:499:33 | unescape(source) | semmle.label | unescape(source) |
|
||||
| tst.js:499:27:499:32 | source | semmle.label | source |
|
||||
| typeahead.js:20:13:20:45 | target | semmle.label | target |
|
||||
| typeahead.js:20:22:20:45 | documen ... .search | semmle.label | documen ... .search |
|
||||
| typeahead.js:21:12:21:17 | target | semmle.label | target |
|
||||
|
||||
@@ -607,6 +607,10 @@ nodes
|
||||
| tst.js:491:16:491:39 | documen ... .search | semmle.label | documen ... .search |
|
||||
| tst.js:492:18:492:23 | target | semmle.label | target |
|
||||
| tst.js:492:18:492:54 | target. ... "), '') | semmle.label | target. ... "), '') |
|
||||
| tst.js:498:7:498:26 | source | semmle.label | source |
|
||||
| tst.js:498:16:498:26 | window.name | semmle.label | window.name |
|
||||
| tst.js:499:18:499:33 | unescape(source) | semmle.label | unescape(source) |
|
||||
| tst.js:499:27:499:32 | source | semmle.label | source |
|
||||
| typeahead.js:9:28:9:30 | loc | semmle.label | loc |
|
||||
| typeahead.js:10:16:10:18 | loc | semmle.label | loc |
|
||||
| typeahead.js:20:13:20:45 | target | semmle.label | target |
|
||||
@@ -1186,6 +1190,9 @@ edges
|
||||
| tst.js:491:7:491:39 | target | tst.js:492:18:492:23 | target | provenance | |
|
||||
| tst.js:491:16:491:39 | documen ... .search | tst.js:491:7:491:39 | target | provenance | |
|
||||
| tst.js:492:18:492:23 | target | tst.js:492:18:492:54 | target. ... "), '') | provenance | |
|
||||
| tst.js:498:7:498:26 | source | tst.js:499:27:499:32 | source | provenance | |
|
||||
| tst.js:498:16:498:26 | window.name | tst.js:498:7:498:26 | source | provenance | |
|
||||
| tst.js:499:27:499:32 | source | tst.js:499:18:499:33 | unescape(source) | provenance | |
|
||||
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | provenance | |
|
||||
| typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target | provenance | |
|
||||
| typeahead.js:20:22:20:45 | documen ... .search | typeahead.js:20:13:20:45 | target | provenance | |
|
||||
|
||||
@@ -493,3 +493,8 @@ function nonGlobalSanitizer() {
|
||||
$("#foo").html(target.replace(new RegExp("<|>", unknownFlags()), '')); // OK - most likely good. We don't know what the flags are.
|
||||
$("#foo").html(target.replace(new RegExp("<|>", "g"), ''));
|
||||
}
|
||||
|
||||
function FooBar() {
|
||||
let source = window.name; // $ Source
|
||||
$('myId').html(unescape(source)) // $ Alert
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user