Merge pull request #20339 from github/idrissrio/scoped-values

Java: Add MaDs for `java.lang.ScopedValue`
This commit is contained in:
Idriss Riouak
2025-09-10 11:21:34 +02:00
committed by GitHub
6 changed files with 120 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added taint flow model for `java.lang.ScopedValue`.

View File

@@ -0,0 +1,19 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["java.lang", "ScopedValue", False, "where", "(ScopedValue,Object)", "", "Argument[1]", "Argument[0].SyntheticField[java.lang.ScopedValue.boundValue]", "value", "manual"]
- ["java.lang", "ScopedValue", True, "get", "()", "", "Argument[this].SyntheticField[java.lang.ScopedValue.boundValue]", "ReturnValue", "value", "manual"]
- ["java.lang", "ScopedValue", False, "where", "(ScopedValue,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.lang", "ScopedValue$Carrier", False, "where", "(ScopedValue,Object)", "", "Argument[1]", "Argument[0].SyntheticField[java.lang.ScopedValue.boundValue]", "value", "manual"]
- ["java.lang", "ScopedValue$Carrier", False, "where", "(ScopedValue,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.lang", "ScopedValue$Carrier", False, "run", "(Runnable)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["java.lang", "ScopedValue$Carrier", False, "call", "(Callable)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- addsTo:
pack: codeql/java-all
extensible: neutralModel
data:
- ["java.lang", "ScopedValue", "newInstance", "()", "summary", "manual"]
- ["java.lang", "ScopedValue", "isBound", "()", "summary", "manual"]

View File

@@ -0,0 +1,44 @@
import java.lang.ScopedValue;
public class ScopedValueFlowTest {
private static final ScopedValue<String> USER_CONTEXT = ScopedValue.newInstance();
private static final ScopedValue<String> SESSION_ID = ScopedValue.newInstance();
public static String source(String label) {
return "tainted";
}
public static void sink(String value) {}
public static void main(String[] args) {
String userInput = source("");
// Test 1: Basic scoped value binding and retrieval
ScopedValue.where(USER_CONTEXT, userInput)
.run(() -> {
String value = USER_CONTEXT.get();
sink(value); // $ hasTaintFlow
});
// Test 2: Multiple scoped value bindings with chaining
ScopedValue.where(USER_CONTEXT, userInput)
.where(SESSION_ID, "safe-one")
.run(() -> {
String user = USER_CONTEXT.get();
String session = SESSION_ID.get();
sink(user); // $ hasTaintFlow
sink(session); // safe - should NOT have taint flow
});
ScopedValue.where(USER_CONTEXT, userInput)
.run(() -> {
String outer = USER_CONTEXT.get();
ScopedValue.where(USER_CONTEXT, "safe-two")
.run(() -> {
String inner = USER_CONTEXT.get();
sink(inner); // $ SPURIOUS: hasTaintFlow
});
sink(outer); // $ hasTaintFlow
});
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -source 25 -target 25 --enable-preview

View File

@@ -0,0 +1,48 @@
models
| 1 | Summary: java.lang; ScopedValue; false; where; (ScopedValue,Object); ; Argument[1]; Argument[0].SyntheticField[java.lang.ScopedValue.boundValue]; value; manual |
| 2 | Summary: java.lang; ScopedValue; true; get; (); ; Argument[this].SyntheticField[java.lang.ScopedValue.boundValue]; ReturnValue; value; manual |
edges
| ScopedValueFlowTest.java:4:46:4:57 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:19:32:19:43 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | |
| ScopedValueFlowTest.java:4:46:4:57 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:27:31:27:42 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | |
| ScopedValueFlowTest.java:4:46:4:57 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:35:32:35:43 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | |
| ScopedValueFlowTest.java:4:46:4:57 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:38:40:38:51 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | |
| ScopedValueFlowTest.java:14:28:14:37 | source(...) : String | ScopedValueFlowTest.java:17:41:17:49 | userInput : String | provenance | |
| ScopedValueFlowTest.java:14:28:14:37 | source(...) : String | ScopedValueFlowTest.java:24:41:24:49 | userInput : String | provenance | |
| ScopedValueFlowTest.java:14:28:14:37 | source(...) : String | ScopedValueFlowTest.java:33:41:33:49 | userInput : String | provenance | |
| ScopedValueFlowTest.java:17:27:17:38 | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:4:46:4:57 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | |
| ScopedValueFlowTest.java:17:41:17:49 | userInput : String | ScopedValueFlowTest.java:17:27:17:38 | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | MaD:1 |
| ScopedValueFlowTest.java:19:32:19:43 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:19:32:19:49 | get(...) : String | provenance | MaD:2 |
| ScopedValueFlowTest.java:19:32:19:49 | get(...) : String | ScopedValueFlowTest.java:20:22:20:26 | value | provenance | |
| ScopedValueFlowTest.java:24:27:24:38 | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:4:46:4:57 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | |
| ScopedValueFlowTest.java:24:41:24:49 | userInput : String | ScopedValueFlowTest.java:24:27:24:38 | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | MaD:1 |
| ScopedValueFlowTest.java:27:31:27:42 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:27:31:27:48 | get(...) : String | provenance | MaD:2 |
| ScopedValueFlowTest.java:27:31:27:48 | get(...) : String | ScopedValueFlowTest.java:29:22:29:25 | user | provenance | |
| ScopedValueFlowTest.java:33:27:33:38 | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:4:46:4:57 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | |
| ScopedValueFlowTest.java:33:41:33:49 | userInput : String | ScopedValueFlowTest.java:33:27:33:38 | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String | provenance | MaD:1 |
| ScopedValueFlowTest.java:35:32:35:43 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:35:32:35:49 | get(...) : String | provenance | MaD:2 |
| ScopedValueFlowTest.java:35:32:35:49 | get(...) : String | ScopedValueFlowTest.java:41:22:41:26 | outer | provenance | |
| ScopedValueFlowTest.java:38:40:38:51 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | ScopedValueFlowTest.java:38:40:38:57 | get(...) : String | provenance | MaD:2 |
| ScopedValueFlowTest.java:38:40:38:57 | get(...) : String | ScopedValueFlowTest.java:39:30:39:34 | inner | provenance | |
nodes
| ScopedValueFlowTest.java:4:46:4:57 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | semmle.label | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String |
| ScopedValueFlowTest.java:14:28:14:37 | source(...) : String | semmle.label | source(...) : String |
| ScopedValueFlowTest.java:17:27:17:38 | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String | semmle.label | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String |
| ScopedValueFlowTest.java:17:41:17:49 | userInput : String | semmle.label | userInput : String |
| ScopedValueFlowTest.java:19:32:19:43 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | semmle.label | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String |
| ScopedValueFlowTest.java:19:32:19:49 | get(...) : String | semmle.label | get(...) : String |
| ScopedValueFlowTest.java:20:22:20:26 | value | semmle.label | value |
| ScopedValueFlowTest.java:24:27:24:38 | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String | semmle.label | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String |
| ScopedValueFlowTest.java:24:41:24:49 | userInput : String | semmle.label | userInput : String |
| ScopedValueFlowTest.java:27:31:27:42 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | semmle.label | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String |
| ScopedValueFlowTest.java:27:31:27:48 | get(...) : String | semmle.label | get(...) : String |
| ScopedValueFlowTest.java:29:22:29:25 | user | semmle.label | user |
| ScopedValueFlowTest.java:33:27:33:38 | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String | semmle.label | USER_CONTEXT [post update] : ScopedValue [java.lang.ScopedValue.boundValue] : String |
| ScopedValueFlowTest.java:33:41:33:49 | userInput : String | semmle.label | userInput : String |
| ScopedValueFlowTest.java:35:32:35:43 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | semmle.label | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String |
| ScopedValueFlowTest.java:35:32:35:49 | get(...) : String | semmle.label | get(...) : String |
| ScopedValueFlowTest.java:38:40:38:51 | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String | semmle.label | USER_CONTEXT : ScopedValue [java.lang.ScopedValue.boundValue] : String |
| ScopedValueFlowTest.java:38:40:38:57 | get(...) : String | semmle.label | get(...) : String |
| ScopedValueFlowTest.java:39:30:39:34 | inner | semmle.label | inner |
| ScopedValueFlowTest.java:41:22:41:26 | outer | semmle.label | outer |
subpaths
testFailures

View File

@@ -0,0 +1,4 @@
import java
import utils.test.InlineFlowTest
import TaintFlowTest<DefaultFlowConfig>
import TaintFlow::PathGraph