diff --git a/java/indexing/unchecked-split-index.yaml b/java/indexing/unchecked-split-index.yaml new file mode 100644 index 0000000..4be4de4 --- /dev/null +++ b/java/indexing/unchecked-split-index.yaml @@ -0,0 +1,43 @@ +rules: + - id: codevigilant.java.indexing.unchecked-split-index + mode: search + severity: MEDIUM + message: >- + A String.split(...) result is indexed at a positive literal offset + ($N) in the same expression, without first verifying the split-array + length. If the input does not contain enough separator-delimited + segments (e.g. a single-line payload split by a line-break regex, or a + value with fewer comma-separated fields than expected), the access + throws an uncaught ArrayIndexOutOfBoundsException. When the split input + is even partially attacker-influenced (file contents, log/console lines, + request data, structured report payloads), this is an uncaught-exception + denial-of-service (CWE-248 / CWE-754) that aborts the enclosing build, + request, or worker thread. Assign the split result to a variable, check + its length before indexing (and validate each field's format before + parsing it), so malformed input degrades gracefully instead of throwing. + languages: + - java + patterns: + - pattern-either: + - pattern: $S.split($SEP)[$N] + - pattern: $S.split($SEP, $LIMIT)[$N] + - pattern: $S.split($SEP)[$N].$METHOD($ARGS) + - metavariable-regex: + metavariable: $N + regex: '[1-9][0-9]*' + metadata: + cwe: + - "CWE-248: Uncaught Exception" + - "CWE-754: Improper Check for Unusual or Exceptional Conditions" + owasp: + - "A05:2021 - Security Misconfiguration" + technology: + - java + confidence: MEDIUM + category: security + references: + - https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ArrayIndexOutOfBoundsException.html + - https://owasp.org/www-community/vulnerabilities/Denial_of_Service + source: + - semgrep-rule-gap + license: MIT \ No newline at end of file diff --git a/testcases/java/indexing/unchecked-split-index-neg.java b/testcases/java/indexing/unchecked-split-index-neg.java new file mode 100644 index 0000000..803a647 --- /dev/null +++ b/testcases/java/indexing/unchecked-split-index-neg.java @@ -0,0 +1,14 @@ +public class UncheckedSplitIndexNeg { + // guarded: length checked before indexing, index 0 only + public String guarded(String csvResults) { + String[] lines = csvResults.split("[\\r\\n]+"); + if (lines.length < 2) { + return ""; + } + String[] fields = lines[1].split(","); + if (fields.length >= 4) { + return fields[0].trim(); + } + return ""; + } +} \ No newline at end of file diff --git a/testcases/java/indexing/unchecked-split-index-pos.java b/testcases/java/indexing/unchecked-split-index-pos.java new file mode 100644 index 0000000..f645a99 --- /dev/null +++ b/testcases/java/indexing/unchecked-split-index-pos.java @@ -0,0 +1,14 @@ +public class UncheckedSplitIndexPos { + // a single-line file: no second line -> split("[\\r\\n]+")[1] throws AIOOBE + public String parseResults(String csvResults) { + return csvResults.split("[\\r\\n]+")[1]; + } + + public int field(String row) { + return Integer.parseInt(row.split(",")[2].trim()); + } + + public String fieldChained(String row) { + return row.split(",")[3].toUpperCase(); + } +} \ No newline at end of file