mirror of
https://github.com/github/codeql.git
synced 2026-07-05 19:45:29 +02:00
Merge branch 'main' into bazookamusic/avro-updated
This commit is contained in:
4
java/ql/integration-tests/java/subst/code/test1.java
Normal file
4
java/ql/integration-tests/java/subst/code/test1.java
Normal file
@@ -0,0 +1,4 @@
|
||||
class Test {
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
}
|
||||
1
java/ql/integration-tests/java/subst/code/test2.kt
Normal file
1
java/ql/integration-tests/java/subst/code/test2.kt
Normal file
@@ -0,0 +1 @@
|
||||
fun main() {}
|
||||
5
java/ql/integration-tests/java/subst/file.expected
Normal file
5
java/ql/integration-tests/java/subst/file.expected
Normal file
@@ -0,0 +1,5 @@
|
||||
| file://:0:0:0:0 | | |
|
||||
| file://:0:0:0:0 | | |
|
||||
| file://Z:/Test.class:0:0:0:0 | Test | relative |
|
||||
| file://Z:/test1.java:0:0:0:0 | test1 | relative |
|
||||
| file://Z:/test2.kt:0:0:0:0 | test2 | relative |
|
||||
9
java/ql/integration-tests/java/subst/file.ql
Normal file
9
java/ql/integration-tests/java/subst/file.ql
Normal file
@@ -0,0 +1,9 @@
|
||||
import java
|
||||
|
||||
from File f, string relative
|
||||
where
|
||||
not f.getURL().matches("file:///modules/%") and
|
||||
not f.getURL().matches("file:///!unknown-binary-location/kotlin/%") and
|
||||
not f.getURL().matches("%/ql/java/kotlin-extractor/%") and
|
||||
if exists(f.getRelativePath()) then relative = "relative" else relative = ""
|
||||
select f, relative
|
||||
7
java/ql/integration-tests/java/subst/test.py
Normal file
7
java/ql/integration-tests/java/subst/test.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import runs_on
|
||||
|
||||
|
||||
@runs_on.windows
|
||||
def test(codeql, java, cwd, subst_drive):
|
||||
drive = subst_drive(cwd / "code")
|
||||
codeql.database.create(command=["javac test1.java", "kotlinc test2.kt"], source_root=drive)
|
||||
@@ -1,4 +1,10 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["org.apache.hc.client5.http.protocol", "RedirectLocations", True, "add", "(URI)", "", "Argument[0]", "Argument[this].Element", "value", "hq-manual"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: neutralModel
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["org.apache.hc.client5.http.protocol", "RedirectLocations", True, "add", "(URI)", "", "Argument[0]", "Argument[this].Element", "value", "hq-manual"]
|
||||
@@ -247,8 +247,8 @@ private predicate simpleLocalFlowStep0(Node node1, Node node2, string model) {
|
||||
or
|
||||
cloneStep(node1, node2) and model = "CloneStep"
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
|
||||
node2.(FlowSummaryNode).getSummaryNode(), true, model)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1, node2.(FlowSummaryNode).getSummaryNode(),
|
||||
true, model)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,6 +41,8 @@ module Input implements InputSig<Location, DataFlowImplSpecific::JavaDataFlow> {
|
||||
|
||||
class SinkBase = Void;
|
||||
|
||||
class FlowSummaryCallBase = Void;
|
||||
|
||||
predicate neutralElement(
|
||||
Input::SummarizedCallableBase c, string kind, string provenance, boolean isExact
|
||||
) {
|
||||
@@ -144,6 +146,10 @@ private module TypesInput implements Impl::Private::TypesInputSig {
|
||||
}
|
||||
|
||||
private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
Impl::Private::SummaryNode getSummaryNode(Node n) {
|
||||
result = n.(FlowSummaryNode).getSummaryNode()
|
||||
}
|
||||
|
||||
DataFlowCall getACall(Public::SummarizedCallable sc) {
|
||||
sc = viableCallable(result).asSummarizedCallable()
|
||||
}
|
||||
|
||||
@@ -145,8 +145,8 @@ private module Cached {
|
||||
)
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src.(DataFlowPrivate::FlowSummaryNode)
|
||||
.getSummaryNode(), sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src,
|
||||
sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -234,8 +234,3 @@ subpaths
|
||||
| use.kt:9:14:9:25 | taint(...) : Closeable | use.kt:9:31:9:36 | it : Closeable | use.kt:9:33:9:34 | it : Closeable | use.kt:9:14:9:36 | use(...) |
|
||||
| with.kt:7:19:7:30 | taint(...) : String | with.kt:7:33:7:40 | $this$with : String | with.kt:7:35:7:38 | this : String | with.kt:7:14:7:40 | with(...) |
|
||||
testFailures
|
||||
| test.kt:28:14:28:21 | getSecond(...) | Unexpected result: hasTaintFlow=a |
|
||||
| test.kt:35:14:35:27 | component1(...) | Unexpected result: hasTaintFlow=d |
|
||||
| test.kt:41:14:41:22 | getSecond(...) | Unexpected result: hasTaintFlow=e |
|
||||
| test.kt:53:14:53:24 | getDuration(...) | Unexpected result: hasTaintFlow=f |
|
||||
| test.kt:58:14:58:29 | component2(...) | Unexpected result: hasTaintFlow=g |
|
||||
|
||||
@@ -25,20 +25,20 @@ class Test {
|
||||
val p = Pair(taint("a"), "")
|
||||
sink(p) // $ hasTaintFlow=a
|
||||
sink(p.component1()) // $ hasTaintFlow=a
|
||||
sink(p.second)
|
||||
sink(p.second) // $ SPURIOUS: hasTaintFlow=a
|
||||
|
||||
sink(taint("b").capitalize()) // $ hasTaintFlow=b
|
||||
sink(taint("c").replaceFirstChar { _ -> 'x' }) // $ hasTaintFlow=c
|
||||
|
||||
val t = Triple("", taint("d"), "")
|
||||
sink(t) // $ hasTaintFlow=d
|
||||
sink(t.component1())
|
||||
sink(t.component1()) // $ SPURIOUS: hasTaintFlow=d
|
||||
sink(t.second) // $ hasTaintFlow=d
|
||||
|
||||
val p1 = taint("e") to ""
|
||||
sink(p1) // $ hasTaintFlow=e
|
||||
sink(p1.component1()) // $ hasTaintFlow=e
|
||||
sink(p1.second)
|
||||
sink(p1.second) // $ SPURIOUS: hasTaintFlow=e
|
||||
|
||||
val l = p.toList()
|
||||
sink(l) // $ hasTaintFlow=a
|
||||
@@ -50,12 +50,12 @@ class Test {
|
||||
val tv = TimedValue(taint("f"), Duration.parse(""))
|
||||
sink(tv) // $ hasTaintFlow=f
|
||||
sink(tv.component1()) // $ hasTaintFlow=f
|
||||
sink(tv.duration)
|
||||
sink(tv.duration) // $ SPURIOUS: hasTaintFlow=f
|
||||
|
||||
val mg0 = MatchGroup(taint("g"), IntRange(0, 10))
|
||||
sink(mg0) // $ hasTaintFlow=g
|
||||
sink(mg0.value) // $ hasTaintFlow=g
|
||||
sink(mg0.component2())
|
||||
sink(mg0.component2()) // $ SPURIOUS: hasTaintFlow=g
|
||||
|
||||
val iv = IndexedValue<String>(5, taint("h"))
|
||||
sink(iv) // $ hasTaintFlow=h
|
||||
@@ -72,4 +72,4 @@ class Test {
|
||||
sink(x.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,8 +234,3 @@ subpaths
|
||||
| use.kt:9:14:9:25 | taint(...) : Closeable | use.kt:9:31:9:36 | it : Closeable | use.kt:9:33:9:34 | it : Closeable | use.kt:9:14:9:36 | use(...) |
|
||||
| with.kt:7:19:7:30 | taint(...) : String | with.kt:7:33:7:40 | $this$with : String | with.kt:7:35:7:38 | this : String | with.kt:7:14:7:40 | with(...) |
|
||||
testFailures
|
||||
| test.kt:28:14:28:21 | getSecond(...) | Unexpected result: hasTaintFlow=a |
|
||||
| test.kt:35:14:35:27 | component1(...) | Unexpected result: hasTaintFlow=d |
|
||||
| test.kt:41:14:41:22 | getSecond(...) | Unexpected result: hasTaintFlow=e |
|
||||
| test.kt:53:14:53:24 | getDuration(...) | Unexpected result: hasTaintFlow=f |
|
||||
| test.kt:58:14:58:29 | component2(...) | Unexpected result: hasTaintFlow=g |
|
||||
|
||||
@@ -25,20 +25,20 @@ class Test {
|
||||
val p = Pair(taint("a"), "")
|
||||
sink(p) // $ hasTaintFlow=a
|
||||
sink(p.component1()) // $ hasTaintFlow=a
|
||||
sink(p.second)
|
||||
sink(p.second) // $ SPURIOUS: hasTaintFlow=a
|
||||
|
||||
sink(taint("b").capitalize()) // $ hasTaintFlow=b
|
||||
sink(taint("c").replaceFirstChar { _ -> 'x' }) // $ hasTaintFlow=c
|
||||
|
||||
val t = Triple("", taint("d"), "")
|
||||
sink(t) // $ hasTaintFlow=d
|
||||
sink(t.component1())
|
||||
sink(t.component1()) // $ SPURIOUS: hasTaintFlow=d
|
||||
sink(t.second) // $ hasTaintFlow=d
|
||||
|
||||
val p1 = taint("e") to ""
|
||||
sink(p1) // $ hasTaintFlow=e
|
||||
sink(p1.component1()) // $ hasTaintFlow=e
|
||||
sink(p1.second)
|
||||
sink(p1.second) // $ SPURIOUS: hasTaintFlow=e
|
||||
|
||||
val l = p.toList()
|
||||
sink(l) // $ hasTaintFlow=a
|
||||
@@ -50,12 +50,12 @@ class Test {
|
||||
val tv = TimedValue(taint("f"), Duration.parse(""))
|
||||
sink(tv) // $ hasTaintFlow=f
|
||||
sink(tv.component1()) // $ hasTaintFlow=f
|
||||
sink(tv.duration)
|
||||
sink(tv.duration) // $ SPURIOUS: hasTaintFlow=f
|
||||
|
||||
val mg0 = MatchGroup(taint("g"), IntRange(0, 10))
|
||||
sink(mg0) // $ hasTaintFlow=g
|
||||
sink(mg0.value) // $ hasTaintFlow=g
|
||||
sink(mg0.component2())
|
||||
sink(mg0.component2()) // $ SPURIOUS: hasTaintFlow=g
|
||||
|
||||
val iv = IndexedValue<String>(5, taint("h"))
|
||||
sink(iv) // $ hasTaintFlow=h
|
||||
@@ -72,4 +72,4 @@ class Test {
|
||||
sink(x.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,3 @@ nodes
|
||||
| BadMacUse.java:146:48:146:57 | ciphertext : byte[] | semmle.label | ciphertext : byte[] |
|
||||
| BadMacUse.java:152:42:152:51 | ciphertext | semmle.label | ciphertext |
|
||||
subpaths
|
||||
testFailures
|
||||
| BadMacUse.java:50:56:50:66 | // $ Source | Missing result: Source |
|
||||
| BadMacUse.java:63:118:63:128 | // $ Source | Missing result: Source |
|
||||
| BadMacUse.java:92:31:92:35 | bytes : byte[] | Unexpected result: Source |
|
||||
| BadMacUse.java:146:95:146:105 | // $ Source | Missing result: Source |
|
||||
|
||||
@@ -30,8 +30,3 @@ nodes
|
||||
| BadMacUse.java:118:83:118:84 | iv : byte[] | semmle.label | iv : byte[] |
|
||||
| BadMacUse.java:124:42:124:51 | ciphertext | semmle.label | ciphertext |
|
||||
subpaths
|
||||
testFailures
|
||||
| BadMacUse.java:63:118:63:128 | // $ Source | Missing result: Source |
|
||||
| BadMacUse.java:92:16:92:36 | doFinal(...) : byte[] | Unexpected result: Source |
|
||||
| BadMacUse.java:124:42:124:51 | ciphertext | Unexpected result: Alert |
|
||||
| BadMacUse.java:146:95:146:105 | // $ Source | Missing result: Source |
|
||||
|
||||
@@ -44,8 +44,3 @@ nodes
|
||||
| BadMacUse.java:146:48:146:57 | ciphertext : byte[] [[]] : Object | semmle.label | ciphertext : byte[] [[]] : Object |
|
||||
| BadMacUse.java:152:42:152:51 | ciphertext | semmle.label | ciphertext |
|
||||
subpaths
|
||||
testFailures
|
||||
| BadMacUse.java:50:56:50:66 | // $ Source | Missing result: Source |
|
||||
| BadMacUse.java:139:79:139:90 | input : byte[] | Unexpected result: Source |
|
||||
| BadMacUse.java:146:95:146:105 | // $ Source | Missing result: Source |
|
||||
| BadMacUse.java:152:42:152:51 | ciphertext | Unexpected result: Alert |
|
||||
|
||||
@@ -47,7 +47,7 @@ class BadMacUse {
|
||||
SecretKey encryptionKey = new SecretKeySpec(encryptionKeyBytes, "AES");
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, encryptionKey, new SecureRandom());
|
||||
byte[] plaintext = cipher.doFinal(ciphertext); // $ Source
|
||||
byte[] plaintext = cipher.doFinal(ciphertext); // $ Source[java/quantum/examples/bad-mac-order-decrypt-to-mac]
|
||||
|
||||
// Now verify MAC (too late)
|
||||
SecretKey macKey = new SecretKeySpec(macKeyBytes, "HmacSHA256");
|
||||
@@ -60,7 +60,7 @@ class BadMacUse {
|
||||
}
|
||||
}
|
||||
|
||||
public void BadMacOnPlaintext(byte[] encryptionKeyBytes, byte[] macKeyBytes, byte[] plaintext) throws Exception {// $ Source
|
||||
public void BadMacOnPlaintext(byte[] encryptionKeyBytes, byte[] macKeyBytes, byte[] plaintext) throws Exception {// $ Source[java/quantum/examples/bad-mac-order-encrypt-plaintext-also-in-mac]
|
||||
// Create keys directly from provided byte arrays
|
||||
SecretKey encryptionKey = new SecretKeySpec(encryptionKeyBytes, "AES");
|
||||
SecretKey macKey = new SecretKeySpec(macKeyBytes, "HmacSHA256");
|
||||
@@ -89,7 +89,7 @@ class BadMacUse {
|
||||
|
||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
|
||||
cipher.init(mode, secretKeySpec, ivParameterSpec);
|
||||
return cipher.doFinal(bytes);
|
||||
return cipher.doFinal(bytes); // $ Source[java/quantum/examples/bad-mac-order-decrypt-then-mac] Source[java/quantum/examples/bad-mac-order-decrypt-to-mac]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,7 +121,7 @@ class BadMacUse {
|
||||
SecretKey macKey = new SecretKeySpec(macKeyBytes, "HmacSHA256");
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(macKey);
|
||||
byte[] computedMac = mac.doFinal(ciphertext); // False Positive
|
||||
byte[] computedMac = mac.doFinal(ciphertext); // $ SPURIOUS: Alert[java/quantum/examples/bad-mac-order-decrypt-to-mac]
|
||||
|
||||
// Concatenate ciphertext and MAC
|
||||
byte[] output = new byte[ciphertext.length + computedMac.length];
|
||||
@@ -136,20 +136,20 @@ class BadMacUse {
|
||||
* The function decrypts THEN computes the MAC on the plaintext.
|
||||
* It should have the MAC computed on the ciphertext first.
|
||||
*/
|
||||
public void decryptThenMac(byte[] encryptionKeyBytes, byte[] macKeyBytes, byte[] input) throws Exception {
|
||||
public void decryptThenMac(byte[] encryptionKeyBytes, byte[] macKeyBytes, byte[] input) throws Exception { // $ SPURIOUS: Source[java/quantum/examples/bad-mac-order-encrypt-plaintext-also-in-mac]
|
||||
// Split input into ciphertext and MAC
|
||||
int macLength = 32; // HMAC-SHA256 output length
|
||||
byte[] ciphertext = Arrays.copyOfRange(input, 0, input.length - macLength);
|
||||
byte[] receivedMac = Arrays.copyOfRange(input, input.length - macLength, input.length);
|
||||
|
||||
// Decrypt first (unsafe)
|
||||
byte[] plaintext = decryptUsingWrapper(ciphertext, encryptionKeyBytes, new byte[16]); // $ Source
|
||||
byte[] plaintext = decryptUsingWrapper(ciphertext, encryptionKeyBytes, new byte[16]);
|
||||
|
||||
// Now verify MAC (too late)
|
||||
SecretKey macKey = new SecretKeySpec(macKeyBytes, "HmacSHA256");
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(macKey);
|
||||
byte[] computedMac = mac.doFinal(ciphertext); // $ Alert[java/quantum/examples/bad-mac-order-decrypt-then-mac], False positive for Plaintext reuse
|
||||
byte[] computedMac = mac.doFinal(ciphertext); // $ Alert[java/quantum/examples/bad-mac-order-decrypt-then-mac] SPURIOUS: Alert[java/quantum/examples/bad-mac-order-encrypt-plaintext-also-in-mac]
|
||||
|
||||
if (!MessageDigest.isEqual(receivedMac, computedMac)) {
|
||||
throw new SecurityException("MAC verification failed");
|
||||
|
||||
@@ -126,5 +126,3 @@ nodes
|
||||
| InsecureIVorNonceSource.java:202:54:202:55 | iv : byte[] | semmle.label | iv : byte[] |
|
||||
| InsecureIVorNonceSource.java:206:51:206:56 | ivSpec | semmle.label | ivSpec |
|
||||
subpaths
|
||||
testFailures
|
||||
| InsecureIVorNonceSource.java:42:21:42:21 | 1 : Number | Unexpected result: Source |
|
||||
|
||||
@@ -39,7 +39,7 @@ public class InsecureIVorNonceSource {
|
||||
public byte[] encryptWithStaticIvByteArray(byte[] key, byte[] plaintext) throws Exception {
|
||||
byte[] iv = new byte[16];
|
||||
for (byte i = 0; i < iv.length; i++) {
|
||||
iv[i] = 1;
|
||||
iv[i] = 1; // $ Source[java/quantum/examples/insecure-iv-or-nonce]
|
||||
}
|
||||
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
|
||||
@@ -40,11 +40,11 @@ public class Test {
|
||||
* SAST/CBOM: - Parent: PBKDF2. - Iteration count is only 10, which is far
|
||||
* below acceptable security standards. - Flagged as insecure.
|
||||
*/
|
||||
public void pbkdf2LowIteration(String password, int iterationCount) throws Exception { // $ Source
|
||||
public void pbkdf2LowIteration(String password, int iterationCount) throws Exception { // $ Source[java/quantum/examples/unknown-kdf-iteration-count]
|
||||
byte[] salt = generateSalt(16);
|
||||
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, 256); // $ Alert[java/quantum/examples/unknown-kdf-iteration-count]
|
||||
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, 256);
|
||||
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
|
||||
byte[] key = factory.generateSecret(spec).getEncoded();
|
||||
byte[] key = factory.generateSecret(spec).getEncoded(); // $ Alert[java/quantum/examples/unknown-kdf-iteration-count]
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
#select
|
||||
| Test.java:47:22:47:49 | KeyDerivation | Key derivation operation with unknown iteration: $@ | Test.java:43:53:43:70 | iterationCount | iterationCount |
|
||||
testFailures
|
||||
| Test.java:45:94:45:154 | // $ Alert[java/quantum/examples/unknown-kdf-iteration-count] | Missing result: Alert[java/quantum/examples/unknown-kdf-iteration-count] |
|
||||
| Test.java:47:22:47:49 | Key derivation operation with unknown iteration: $@ | Unexpected result: Alert |
|
||||
|
||||
@@ -12,5 +12,3 @@ nodes
|
||||
| Test.java:58:30:58:38 | 1_000_000 : Number | semmle.label | 1_000_000 : Number |
|
||||
| Test.java:59:72:59:85 | iterationCount | semmle.label | iterationCount |
|
||||
subpaths
|
||||
testFailures
|
||||
| Test.java:43:92:43:102 | // $ Source | Missing result: Source |
|
||||
|
||||
@@ -13,8 +13,7 @@ predicate taintFlowUpdate(DataFlow::ParameterNode p1, DataFlow::ParameterNode p2
|
||||
}
|
||||
|
||||
predicate summaryStep(FlowSummaryNode src, FlowSummaryNode sink) {
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src.getSummaryNode(), sink.getSummaryNode(),
|
||||
false, _) or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink.getSummaryNode(), false, _) or
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(src.getSummaryNode(), _, sink.getSummaryNode()) or
|
||||
FlowSummaryImpl::Private::Steps::summaryStoreStep(src.getSummaryNode(), _, sink.getSummaryNode())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user