Skip to content

Commit 0781cb7

Browse files
author
Stephan Brandauer
committed
Java: automodel application mode: add isVarargsArray metadata value
1 parent 5abf776 commit 0781cb7

7 files changed

+33
-23
lines changed

java/ql/src/Telemetry/AutomodelApplicationModeCharacteristics.qll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ class ApplicationModeMetadataExtractor extends string {
213213

214214
predicate hasMetadata(
215215
Endpoint e, string package, string type, string subtypes, string name, string signature,
216-
string input
216+
string input, string isVarargsArray
217217
) {
218218
exists(Callable callable |
219219
e.getCall().getCallee() = callable and
@@ -224,7 +224,10 @@ class ApplicationModeMetadataExtractor extends string {
224224
type = callable.getDeclaringType().getErasure().(RefType).nestedName() and
225225
subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and
226226
name = callable.getName() and
227-
signature = ExternalFlow::paramsString(callable)
227+
signature = ExternalFlow::paramsString(callable) and
228+
if e instanceof ImplicitVarargsArray
229+
then isVarargsArray = "true"
230+
else isVarargsArray = "false"
228231
)
229232
}
230233
}

java/ql/src/Telemetry/AutomodelApplicationModeExtractCandidates.ql

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,18 @@ private import AutomodelJavaUtil
2525
bindingset[limit]
2626
private Endpoint getSampleForSignature(
2727
int limit, string package, string type, string subtypes, string name, string signature,
28-
string input
28+
string input, string isVarargs
2929
) {
3030
exists(int n, int num_endpoints, ApplicationModeMetadataExtractor meta |
3131
num_endpoints =
32-
count(Endpoint e | meta.hasMetadata(e, package, type, subtypes, name, signature, input))
32+
count(Endpoint e |
33+
meta.hasMetadata(e, package, type, subtypes, name, signature, input, isVarargs)
34+
)
3335
|
3436
result =
3537
rank[n](Endpoint e, Location loc |
3638
loc = e.asTop().getLocation() and
37-
meta.hasMetadata(e, package, type, subtypes, name, signature, input)
39+
meta.hasMetadata(e, package, type, subtypes, name, signature, input, isVarargs)
3840
|
3941
e
4042
order by
@@ -53,19 +55,20 @@ private Endpoint getSampleForSignature(
5355
from
5456
Endpoint endpoint, string message, ApplicationModeMetadataExtractor meta, DollarAtString package,
5557
DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature,
56-
DollarAtString input
58+
DollarAtString input, DollarAtString isVarargsArray
5759
where
5860
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
5961
u.appliesToEndpoint(endpoint)
6062
) and
61-
endpoint = getSampleForSignature(9, package, type, subtypes, name, signature, input) and
63+
endpoint =
64+
getSampleForSignature(9, package, type, subtypes, name, signature, input, isVarargsArray) and
6265
// If a node is already a known sink for any of our existing ATM queries and is already modeled as a MaD sink, we
6366
// don't include it as a candidate. Otherwise, we might include it as a candidate for query A, but the model will
6467
// label it as a sink for one of the sink types of query B, for which it's already a known sink. This would result in
6568
// overlap between our detected sinks and the pre-existing modeling. We assume that, if a sink has already been
6669
// modeled in a MaD model, then it doesn't belong to any additional sink types, and we don't need to reexamine it.
6770
not CharacteristicsImpl::isSink(endpoint, _, _) and
68-
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
71+
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, isVarargsArray) and
6972
// The message is the concatenation of all sink types for which this endpoint is known neither to be a sink nor to be
7073
// a non-sink, and we surface only endpoints that have at least one such sink type.
7174
message =
@@ -83,4 +86,5 @@ select endpoint.asNode(),
8386
subtypes, "subtypes", //
8487
name, "name", // method name
8588
signature, "signature", //
86-
input, "input" //
89+
input, "input", //
90+
isVarargsArray, "isVarargsArray"

java/ql/src/Telemetry/AutomodelApplicationModeExtractNegativeExamples.ql

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,16 @@ Endpoint getSampleForCharacteristic(EndpointCharacteristic c, int limit) {
4343
from
4444
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message,
4545
ApplicationModeMetadataExtractor meta, DollarAtString package, DollarAtString type,
46-
DollarAtString subtypes, DollarAtString name, DollarAtString signature, DollarAtString input
46+
DollarAtString subtypes, DollarAtString name, DollarAtString signature, DollarAtString input,
47+
DollarAtString isVarargsArray
4748
where
4849
endpoint = getSampleForCharacteristic(characteristic, 100) and
4950
confidence >= SharedCharacteristics::highConfidence() and
5051
characteristic.hasImplications(any(NegativeSinkType negative), true, confidence) and
5152
// Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly
5253
// certain about in the prompt.
5354
not erroneousEndpoints(endpoint, _, _, _, _, false) and
54-
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
55+
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, isVarargsArray) and
5556
// It's valid for a node to satisfy the logic for both `isSink` and `isSanitizer`, but in that case it will be
5657
// treated by the actual query as a sanitizer, since the final logic is something like
5758
// `isSink(n) and not isSanitizer(n)`. We don't want to include such nodes as negative examples in the prompt, because
@@ -71,4 +72,5 @@ select endpoint.asNode(),
7172
subtypes, "subtypes", //
7273
name, "name", //
7374
signature, "signature", //
74-
input, "input" //
75+
input, "input", //
76+
isVarargsArray, "isVarargsArray" //

java/ql/src/Telemetry/AutomodelApplicationModeExtractPositiveExamples.ql

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ private import AutomodelJavaUtil
1515
from
1616
Endpoint endpoint, SinkType sinkType, ApplicationModeMetadataExtractor meta,
1717
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
18-
DollarAtString signature, DollarAtString input
18+
DollarAtString signature, DollarAtString input, DollarAtString isVarargsArray
1919
where
2020
// Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly
2121
// certain about in the prompt.
2222
not erroneousEndpoints(endpoint, _, _, _, _, false) and
23-
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
23+
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, isVarargsArray) and
2424
// Extract positive examples of sinks belonging to the existing ATM query configurations.
2525
CharacteristicsImpl::isKnownSink(endpoint, sinkType) and
2626
exists(CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()))
@@ -32,4 +32,5 @@ select endpoint.asNode(),
3232
subtypes, "subtypes", //
3333
name, "name", //
3434
signature, "signature", //
35-
input, "input" //
35+
input, "input", //
36+
isVarargsArray, "isVarargsArray"
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
| Test.java:16:3:16:11 | reference | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:16:3:16:11 | reference | CallContext | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input |
2-
| Test.java:21:3:21:10 | supplier | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:21:3:21:10 | supplier | CallContext | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input |
3-
| Test.java:51:3:54:3 | new ..[] { .. } | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:51:3:54:3 | walk(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input |
1+
| Test.java:16:3:16:11 | reference | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:16:3:16:11 | reference | CallContext | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://false:1:1:1:1 | false | isVarargsArray |
2+
| Test.java:21:3:21:10 | supplier | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:21:3:21:10 | supplier | CallContext | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://false:1:1:1:1 | false | isVarargsArray |
3+
| Test.java:51:3:54:3 | new ..[] { .. } | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:51:3:54:3 | walk(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://true:1:1:1:1 | true | isVarargsArray |
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
| Test.java:46:4:46:5 | f2 | known non-sink\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:46:4:46:5 | f2 | CallContext | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input |
2-
| Test.java:52:4:52:4 | p | taint step\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:52:4:52:4 | p | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input |
1+
| Test.java:46:4:46:5 | f2 | known non-sink\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:46:4:46:5 | f2 | CallContext | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://false:1:1:1:1 | false | isVarargsArray |
2+
| Test.java:52:4:52:4 | p | taint step\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:52:4:52:4 | p | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://false:1:1:1:1 | false | isVarargsArray |
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
| Test.java:26:4:26:9 | source | path-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:26:4:26:9 | source | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input |
2-
| Test.java:27:4:27:9 | target | path-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:27:4:27:9 | target | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input |
3-
| Test.java:34:4:34:11 | openPath | path-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:34:4:34:11 | openPath | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input |
1+
| Test.java:26:4:26:9 | source | path-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:26:4:26:9 | source | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://false:1:1:1:1 | false | isVarargsArray |
2+
| Test.java:27:4:27:9 | target | path-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:27:4:27:9 | target | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://false:1:1:1:1 | false | isVarargsArray |
3+
| Test.java:34:4:34:11 | openPath | path-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:34:4:34:11 | openPath | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://false:1:1:1:1 | false | isVarargsArray |

0 commit comments

Comments
 (0)