java/ssrf: allowlist guard not recognized when expressed via Stream/lambda (anyMatch), only via plain equals()/for-loop
- 主要言語
- CodeQL
- スター
- 10.1k
- フォーク
- 2.1k
- 平均マージ
- 2日 15時間
- マージ済み PR(30日)
- 141
説明
### Query
`java/ssrf` (Server-side request forgery), Java/Kotlin `Security/CWE-918`
### Summary
The SSRF sanitizer-guard recognition for this query does not appear to model an allowlist check expressed via `Arrays.stream(...).anyMatch(...)` (or other `Stream`/lambda/method-reference based equality checks) as taint-clearing, even though a functionally identical check written as a plain `for` loop with `.equals()`/`.equalsIgnoreCase()` calls *is* recognized and clears the alert.
### Example (not recognized — alert fires)
```java
private static boolean isAllowedHost(String host, String... allowedHosts) {
return Arrays.stream(allowedHosts).anyMatch(host::equalsIgnoreCase);
}
void fetch(String userUrl) {
URI uri = new URI(userUrl);
if (isAllowedHost(uri.getHost(), "example.com")) {
uri.toURL().openConnection(); // still flagged as SSRF sink
}
}
```
### Example (recognized — alert clears)
```java
private static boolean isAllowedHost(String host, String... allowedHosts) {
for (String allowed : allowedHosts) {
if (allowed.equalsIgnoreCase(host)) {
return true;
}
}
return false;
}
```
(Identical behavior/contract; only the loop construct differs.)
### Why this matters
Lambda-based and `Stream`-based collection idioms (`anyMatch`, `Set.of(...).contains(...)`, etc.) have been idiomatic, widely-used Java since Java 8 (2014). A sanitizer-guard recognizer that only matches a narrow inline `if (LITERAL.equals(x))`/plain-loop shape — and not equivalent `Stream`/lambda forms — produces false positives that push teams toward less readable, less idiomatic code purely to satisfy the analyzer, with no corresponding security benefit. This also seems inconsistent with sanitizer/guard modeling in other CodeQL queries that do recognize `Collection.contains(...)`-style checks.
### Ask
Could the `java/ssrf` (and ideally the shared sanitizer-guard library used across similar taint-tracking queries) be extended to recognize equality-based allowlist checks expressed via common `Stream`/lambda idioms (`Arrays.stream(...).anyMatch(x::equals)`, `Collection.contains(x)`, `Set.of(...).contains(x)`) as taint-clearing guards, equivalent to their imperative-loop counterparts?
Happy to provide a minimal reproducible test case/repo if useful.
コントリビューションガイド
調査の方向性
java/ssrf クエリと、それが使用する共有 sanitizer-guard ライブラリから始め、既存の equals() とループ形式がどのようにモデル化されているかを調べます。Arrays.stream(...).anyMatch(...)、method-reference、contains(...) の例に対するリグレッションカバレッジを追加し、認識された allowlist チェックによって他のケースを弱めることなく SSRF アラートがクリアされることを検証します。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- java
- 領域
- devtools, security
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 静か
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 45/100