Skip to content

feat(scan): command injection, SSRF and traversal for Java; traversal and template escaping for Go (v0.7.0) - #91

Merged
ralyodio merged 2 commits into
masterfrom
feat/go-java-rules
Aug 10, 2026
Merged

feat(scan): command injection, SSRF and traversal for Java; traversal and template escaping for Go (v0.7.0)#91
ralyodio merged 2 commits into
masterfrom
feat/go-java-rules

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Release 0.7.0.

The gap

Command injection, SSRF and path traversal were implemented for JavaScript and, in part, for Go — and never for Java. The same defect in the same codebase was reported or not depending on which file it lived in.

Rule counts before this PR:

language rules
javascript / typescript 13
python 8
shell 7
java 5
ruby 4
go 3

Java and Go were the thin ones, and what was missing from them was not exotic — it was the OWASP top of the list.

Added

Java

rule CWE
java-runtime-exec-concatenation CWE-78
java-ssrf-outbound-request CWE-918
java-request-path-traversal CWE-22
java-broken-cipher CWE-327

Go

rule CWE
go-request-path-traversal CWE-22
go-template-escaping-bypass CWE-79

Deliberately not added

TLS verification, weak hashing and insecure randomness. tls-verification-disabled, weak-hash-on-credential and insecure-randomness-for-secret are language-agnostic and already cover both languages — the first already matches Go's InsecureSkipVerify, the second already matches Java's MessageDigest.getInstance("MD5"). Adding per-language copies would double-report the same line.

Worth noting the existing pair are scoped to credential and secret context rather than firing on every MD5. That is the right call — MD5 as a cache key is not a vulnerability — and this PR does not disturb it.

Each rule is built against the corrected shape

  • exec(new String[]{"git", "checkout", branch}) — the argv form — is not matched; only the single-string concatenation is.
  • new URL("https://api.example.com/v1/status") is not matched; a computed URL is.
  • A getCanonicalPath().startsWith(base) check below the construction exonerates both traversal rules.
  • Cipher.getInstance("AES/GCM/NoPadding") is not matched. Bare Cipher.getInstance("AES") is — the JCE resolves it to AES/ECB/PKCS5Padding, so the default is the mode the rule exists to catch.
  • template.HTML("<br>") on a literal is not matched; a conversion of a variable is.

Verification

ionic-team/capacitor: unchanged at 13 findings across 146 Java files. Zero false positives from six new rules.

That number is load-bearing, so I checked what it was actually exercising rather than assuming absence of matching code:

  • 0 Runtime.getRuntime() call sites — nothing for that rule to hit.
  • 0 Cipher.getInstance call sites.
  • 2 concatenated new File(...) sites, both new File(path + "capacitor.config.json") — a constant filename on an internal config path. needsContext correctly holds them.
  • 6 distinct new URL(variable) sites, all taking config or plugin-internal values that match none of Java's untrusted-input patterns. Correctly silent.

So: no false positives, and the silences are explained rather than lucky. The unit tests carry the positive cases.

debtap: unchanged at 8. 111 tests, up from 105. tsc --noEmit clean.

… and template escaping for Go

Release 0.7.0.

Command injection, SSRF and path traversal were implemented for JavaScript
and, in part, for Go, and never for Java. The same defect in the same
codebase was reported or not depending on which file it lived in — Java had
five rules to JavaScript's thirteen, and none of them covered a class this
common.

Java: Runtime.exec built by concatenation (CWE-78), outbound request to a
computed URL (CWE-918), file path built from request data (CWE-22), broken
cipher or ECB mode (CWE-327).

Go: file path built from request data (CWE-22), value marked as pre-escaped
HTML (CWE-79).

Deliberately not added: TLS verification, weak hashing and insecure
randomness. `tls-verification-disabled`, `weak-hash-on-credential` and
`insecure-randomness-for-secret` are language-agnostic and already cover
both languages, including Go's InsecureSkipVerify and Java's MessageDigest.
Duplicating them per-language would double-report.

Each rule is built against the corrected shape: the argv form of exec is not
matched, a constant URL is not matched, a canonical-path containment check
exonerates the traversal rules, AES/GCM is not matched, and
template.HTML on a literal is not matched. Bare Cipher.getInstance("AES")
is matched, because the JCE resolves it to AES/ECB/PKCS5Padding.

Verified against ionic-team/capacitor: 146 Java files, findings unchanged at
13 — no false positives. The two concatenated `new File` sites there build a
config path from a constant and are correctly left alone by needsContext.
debtap unchanged at 8. 111 tests, up from 105.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment thread apps/cli/src/scan/__tests__/code-rules.test.ts Fixed
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

ThreatCrush Security Scan

156 finding(s)

HIGH/CRITICAL: 14 | MEDIUM: 106 | LOW: 36

Severity Rule Location
HIGH sql-template-interpolation apps/cli/src/scan/__tests__/code-rules.test.ts:31
HIGH secret-aws-access-key apps/cli/src/scan/secret-rules.ts:192
HIGH js-shell-exec-interpolation modules/code-scanner/src/__tests__/sast.test.ts:31
HIGH js-shell-exec-interpolation modules/code-scanner/src/__tests__/sast.test.ts:102
HIGH js-shell-exec-interpolation modules/code-scanner/src/__tests__/sast.test.ts:108
HIGH secret-aws-access-key modules/code-scanner/src/secrets/rules.ts:74
HIGH secret-aws-access-key prd/0003-detect-hardcoded-secrets-before-they-are-committed-or-served.md:126
HIGH sh-eval-expansion .githooks/pre-commit:26
HIGH js-unsafe-yaml-load apps/cli/src/scan/__tests__/code-rules.test.ts:216
HIGH secret-generic-credential modules/spend-guard/config/example.conf.toml:13
HIGH secret-generic-credential modules/spend-guard/README.md:84
HIGH secret-generic-credential PRD.md:268
HIGH sh-remote-script-execution scripts/smoke-test.sh:46
HIGH sh-remote-script-execution scripts/smoke-test.sh:47
MEDIUM insecure-temp-file .githooks/commit-msg:16
MEDIUM insecure-temp-file .githooks/post-commit:20
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/init.ts:70
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/init.ts:79
MEDIUM sql-template-interpolation apps/cli/src/commands/properties.ts:226
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/service.ts:88
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/service.ts:111
MEDIUM sql-template-interpolation apps/cli/src/core/state.ts:121
MEDIUM sql-template-interpolation apps/cli/src/core/state.ts:125
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:31
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:33
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:34
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:35
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:36
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:43
MEDIUM sql-template-interpolation apps/cli/src/daemon/firewall/adapters.ts:49
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:49
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:56
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:63
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:82
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:84
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:85
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:93
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:98
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:105
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:112
MEDIUM sql-template-interpolation apps/cli/src/index.ts:105
MEDIUM sql-template-interpolation apps/cli/src/index.ts:110
MEDIUM sql-template-interpolation apps/cli/src/index.ts:120
MEDIUM js-shell-exec-interpolation apps/cli/src/index.ts:411
MEDIUM sql-string-concatenation apps/cli/src/scan/__tests__/code-rules.test.ts:21
MEDIUM sql-template-interpolation apps/cli/src/scan/__tests__/code-rules.test.ts:35
MEDIUM sql-string-concatenation apps/cli/src/scan/__tests__/code-rules.test.ts:40
MEDIUM sql-string-concatenation apps/cli/src/scan/__tests__/code-rules.test.ts:49
MEDIUM sql-string-concatenation apps/cli/src/scan/__tests__/code-rules.test.ts:53
MEDIUM js-shell-exec-interpolation apps/cli/src/scan/__tests__/code-rules.test.ts:65

…and 106 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

…tures

The self-scan flagged three lines of this file. All three are string
literals holding sample code for another language — a PHP `eval` and a
Java `Runtime.exec` — which the JavaScript rules match because the file
they sit in is TypeScript.

Same treatment as the existing fixtures: an inline disable naming the rule
and why. The Java one is lifted into a variable first, so the suppression
comment attaches to the line the finding is actually on rather than to the
middle of a wrapped expression.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 0f56d28 into master Aug 10, 2026
10 checks passed
@ralyodio
ralyodio deleted the feat/go-java-rules branch August 10, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants