← Back to Feed CACHED · 2026-06-30 00:34:44 · CACHE_KEY CVE-2026-13500
CVE-2026-13500 · CWE-74 · Disclosed 2026-06-28

A weakness has been identified in antlr ANTLR4 up to 4

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

A code-generator that trusts its grammar is like a compiler that trusts its source — yes, technically a flaw, but you fed it the bullets

CVE-2026-13500 sits in tool/src/org/antlr/v4/codegen/model/OutputFile.java inside ANTLR4's Grammar Action Block Handler. ANTLR4 is a *parser generator* — a developer build-time tool that consumes .g4 grammar files and emits parser source code in Java/C#/Python/Go/etc. The flaw (CWE-74) lets a crafted action block inside a grammar inject arbitrary code into the generated output, which then compiles into whatever target the developer is building. Affected: all ANTLR4 releases through and including 4.13.2; the runtime libraries shipped to production are *not* the target — only the antlr4 tool jar / CLI used at build time.

Vendor severity of HIGH (7.3) with AV:N/PR:N/UI:N is *technically defensible* under literal CVSS rules (a grammar file can arrive over a network), but it badly misrepresents the real exposure. There is no listening service. No production host runs the ANTLR tool. The 'attack' requires a developer or CI pipeline to voluntarily feed an attacker-supplied grammar into antlr4 -Dlanguage=… Foo.g4 — which is functionally identical to running javac on attacker source. Treat this as LOW for the fleet; the only real action item is in your dev-tooling and CI policy.

"Build-time code generator flaw. To exploit, you must compile a malicious grammar — that's already a trust violation, not a vulnerability."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Attacker authors a malicious .g4 grammar

Adversary crafts a grammar file containing a poisoned action block — the { … } embedded target-language snippet that ANTLR copies verbatim into generated parser code. The flaw is that OutputFile.java fails to neutralize special elements when emitting these blocks, so injected payload escapes its intended scope into the generated source file. Tooling for this is trivial: any text editor.
Conditions required:
  • Public exploit / PoC referenced in the disclosure
  • Knowledge of the victim's target language (Java/Go/Python/etc.)
Where this breaks in practice:
  • Grammar files are rarely consumed from untrusted parties — they're vendored into repos or pulled from known upstreams
Detection/coverage: No scanner signature exists for malicious .g4 content; static-analysis tools don't inspect grammar action blocks.
STEP 02

Victim runs ANTLR4 tool against the grammar

Developer or CI job invokes antlr4 evil.g4 (or the Maven/Gradle/SBT antlr4 plugin) and the tool emits parser source containing the injected payload. This is the entire vulnerability — ANTLR4 itself does *not* execute the payload at codegen time; it bakes it into the generated .java/.go/.py file.
Conditions required:
  • Victim must voluntarily consume the attacker grammar
  • ANTLR4 ≤ 4.13.2 tool jar in build path
Where this breaks in practice:
  • No org I've ever seen pulls third-party .g4 files at build time without review
  • Grammars are typically committed to the repo and reviewed in PR
Detection/coverage: PR review of grammar changes catches this trivially if reviewers know what action blocks look like.
STEP 03

Generated parser is compiled and shipped

The poisoned generated source is then compiled by the normal toolchain (javac, go build, etc.) and linked into the application. At this point the malicious code is indistinguishable from any other legitimately-authored source the build pipeline trusts.
Conditions required:
  • Build pipeline doesn't diff generated artifacts
  • No SAST step over generated code
Where this breaks in practice:
  • SAST on the build output catches obvious shells/eval
  • Reproducible-build attestation breaks if the grammar source is tampered post-review
Detection/coverage: SAST (Semgrep, CodeQL, Checkmarx) over generated parser code will flag suspicious calls — but most shops exclude generated code from SAST, which is the real failure mode.
STEP 04

Payload executes in the built application

When the host application instantiates the generated parser (or just loads the class), the injected code runs in the application's process context. Impact is bounded by whatever the affected application is — could be a desktop tool, a CLI, a microservice. There is no privilege escalation path inherent to the bug.
Conditions required:
  • Built application is deployed and runs the parser code
Where this breaks in practice:
  • Blast radius limited to the one application that ingested the bad grammar
  • Not a wormable / lateral-movement primitive
Detection/coverage: EDR sees the resulting process behavior (process spawn, network beacon) the same as any malicious binary.
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. Not on CISA KEV. No GreyNoise tags. No reports of weaponization against build pipelines.
Public PoCDisclosure references a *public exploit*, but no widely-circulated weaponized grammar has surfaced on GitHub or Exploit-DB as of disclosure week.
EPSS0.00311 (≈0.3%) — bottom-decile, consistent with build-tool flaws that score high on paper but never get exploited at scale.
KEV statusNot listed. CISA has historically declined to KEV developer build tools absent supply-chain evidence.
CVSS interpretationCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L = 7.3. The AV:N / UI:N combo is the misleading part — it treats 'attacker can ship a file' as 'no user interaction', which inflates this class of bug. CVSS 4.0 rescored to 6.9 (MEDIUM), which is closer to reality.
Affected versionsANTLR4 tool ≤ 4.13.2 (all releases through current). Runtime libraries (antlr4-runtime jars, antlr4-python3-runtime, etc.) are NOT the vulnerable component.
Fixed versionNo vendor fix published. Vendor was contacted pre-disclosure and *did not respond*. Treat as 0-day from vendor's POV — no patched build to track.
Exposure dataNo listening service — Shodan/Censys/FOFA inapplicable. Real exposure population = orgs whose CI runs ANTLR4 on untrusted grammar input, which is *vanishingly rare*.
DisclosurePublished 2026-06-28, CWE-74. Coordinated disclosure attempt failed (vendor non-response).
ReporterReported via VulDB/CIRCL channel; not attributed to a major research org.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.1/10)

Downgraded from vendor HIGH (7.3) to LOW (3.1) because the single most decisive factor is that the affected component is a *developer build-time tool*, not a runtime service — exploitation requires the victim to voluntarily compile an attacker-supplied grammar file, which is a code-trust violation regardless of any ANTLR bug. There is no exposed attack surface on production hosts.

HIGH that this is a build-tool issue, not a runtime issue
HIGH that the affected population on production fleet is effectively zero
MEDIUM that no vendor patch will arrive on a short timeline given non-response

Why this verdict

  • Build-time only: OutputFile.java lives in the tool/ source tree — the ANTLR4 *generator*, not the antlr4-runtime shipped with applications. Your 10,000-host fleet does not run this component.
  • Requires voluntary grammar ingestion: Exploit assumes the victim runs antlr4 evil.g4. Grammars are essentially source code; consuming an untrusted one is equivalent to git clone && make on a stranger's repo. The bug is downstream of an already-broken trust decision.
  • Role multiplier (low-value role — developer workstation / CI runner): Chain succeeds, blast radius = one developer or one build job. No fleet pivot.
  • Role multiplier (typical role — internal CI building first-party grammars): Chain *fails* — grammars are vendored, reviewed in PR, not attacker-supplied. Blast radius = zero.
  • Role multiplier (high-value role — public grammar registry / SaaS that compiles user-submitted grammars): Chain succeeds, blast radius = single tenant container, contained by sandbox. Such services are <0.01% of ANTLR4 install base — does not raise the floor.
  • EPSS 0.3% + no KEV + no in-the-wild reports confirm market consensus that this is not an active threat.
  • CVSS AV:N/UI:N is artifact, not reality: The vector treats file delivery as network attack with no user action. CVSS 4.0 already corrects this to 6.9 MEDIUM; real-world severity is lower still.

Why not higher?

Not MEDIUM/HIGH because there is no production attack surface — the vulnerable code is a developer tool, and no canonical high-value-role deployment (IdP, hypervisor, EDR, CA, backup) uses ANTLR4 at runtime. The role multiplier analysis finds no role where chain success yields fleet, domain, or supply-chain impact at meaningful installed-base share.

Why not lower?

Not IGNORE because there *is* a non-trivial supply-chain edge case: organizations that build language servers, query engines, or parsers from third-party grammars (e.g., language plugins from public registries) do have a real exposure path. Worth documenting and a CI policy update, but not worth waking anyone up.

05 · Compensating Control

What to do — in priority order.

  1. Inventory ANTLR4 tool usage in CI — Grep your build configs (pom.xml, build.gradle, package.json, setup.py, Bazel/Buck rules) for antlr4, antlr4-maven-plugin, antlr4ts-cli. You need to know *which* pipelines invoke the tool before you can scope risk. No mitigation SLA for LOW — fold into normal backlog hygiene.
  2. Enforce that .g4 grammar files come only from trusted sources — Add a CI policy check that fails the build if a .g4 file is added or modified outside an allowlist of vendored upstream paths, without a human review label. Stops the only realistic exploitation path (untrusted grammar ingestion).
  3. Include generated parser code in SAST scope — Most shops exclude generated code from Semgrep/CodeQL because of noise — for ANTLR-generated parsers, add a narrow ruleset that flags Runtime.exec, eval, os.system, exec.Command, dynamic loads. Catches injected payloads at build time.
  4. Pin ANTLR4 tool version and track upstream — If vendor publishes a fix post-disclosure (currently non-responsive), pin to the patched version. Until then, pinning to a known build avoids accidentally pulling a Trojaned distribution.
  5. Document risk acceptance for the LOW verdict — Compliance auditors will see vendor HIGH (7.3) and ask. Pre-empt with a one-paragraph rationale citing build-time scope and trust-boundary analysis.
What doesn't work
  • Patching runtime hosts: the antlr4-runtime library shipped with applications is not the vulnerable component — patching it does nothing.
  • WAF / IDS signatures: there is no network protocol to sign; the 'payload' is a grammar file consumed at build time.
  • EDR on production fleet: EDR sees the result of a poisoned application *after* it's deployed; it does not stop the build-time injection.
  • Disabling ANTLR runtime: would break any application using generated parsers and provides zero security benefit since runtime is not vulnerable.
06 · Verification

Crowdsourced verification payload.

Run on each CI build runner and developer workstation that may invoke ANTLR4. Invoke as ./check_antlr4.sh — no special privileges required (reads filesystem and queries package managers). Outputs VULNERABLE if ANTLR4 tool ≤ 4.13.2 is present, PATCHED if a fixed version is found, UNKNOWN if no ANTLR4 install detected.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# noisgate verification: CVE-2026-13500 — ANTLR4 tool code injection via grammar action block
# Detects ANTLR4 *tool* (not runtime) at version <= 4.13.2 on this host.
set -u

FIXED_VERSION="" # vendor has not published a fix as of 2026-06-30; update when available
MAX_VULN="4.13.2"
FOUND=0
VULN=0

ver_le() {
  # returns 0 (true) if $1 <= $2 by version sort
  [ "$1" = "$2" ] && return 0
  printf '%s\n%s\n' "$1" "$2" | sort -V -C
}

check_jar() {
  local jar="$1"
  local v
  v=$(unzip -p "$jar" META-INF/MANIFEST.MF 2>/dev/null | awk -F': ' '/Implementation-Version/{gsub(/\r/,"");print $2;exit}')
  [ -z "$v" ] && v=$(echo "$jar" | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | tail -1)
  if [ -n "$v" ]; then
    FOUND=1
    echo "[+] Found ANTLR4 tool: $jar (version $v)"
    if ver_le "$v" "$MAX_VULN"; then
      VULN=1
      echo "    -> VULNERABLE (<= $MAX_VULN)"
    fi
  fi
}

# 1. Common jar locations
for path in /usr/local/lib /usr/share/java /opt $HOME/.m2/repository/org/antlr $HOME/.gradle/caches; do
  [ -d "$path" ] || continue
  while IFS= read -r jar; do
    check_jar "$jar"
  done < <(find "$path" -type f \( -iname 'antlr-4*.jar' -o -iname 'antlr4-4*.jar' -o -iname 'antlr4-tool-*.jar' \) 2>/dev/null)
done

# 2. npm antlr4ts-cli / antlr4-tool
if command -v npm >/dev/null 2>&1; then
  for pkg in antlr4ts-cli antlr4-tool antlr4; do
    v=$(npm ls -g --depth=0 "$pkg" 2>/dev/null | grep -oE "$pkg@[0-9.]+" | cut -d@ -f2)
    if [ -n "$v" ]; then
      FOUND=1
      echo "[+] Found npm $pkg@$v"
      ver_le "$v" "$MAX_VULN" && { VULN=1; echo "    -> VULNERABLE"; }
    fi
  done
fi

# 3. pip antlr4-tools
if command -v pip >/dev/null 2>&1; then
  v=$(pip show antlr4-tools 2>/dev/null | awk '/^Version:/{print $2}')
  if [ -n "$v" ]; then
    FOUND=1
    echo "[+] Found pip antlr4-tools $v"
    ver_le "$v" "$MAX_VULN" && { VULN=1; echo "    -> VULNERABLE"; }
  fi
fi

# 4. antlr4 on PATH
if command -v antlr4 >/dev/null 2>&1; then
  v=$(antlr4 2>&1 | grep -oE 'Version [0-9.]+' | awk '{print $2}')
  if [ -n "$v" ]; then
    FOUND=1
    echo "[+] Found antlr4 on PATH: $v"
    ver_le "$v" "$MAX_VULN" && { VULN=1; echo "    -> VULNERABLE"; }
  fi
fi

if [ $VULN -eq 1 ]; then
  echo "RESULT: VULNERABLE"
  exit 2
elif [ $FOUND -eq 1 ]; then
  echo "RESULT: PATCHED"
  exit 0
else
  echo "RESULT: UNKNOWN (no ANTLR4 tool detected on this host)"
  exit 1
fi
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: do nothing urgent on the production fleet — ANTLR4 runtime is not the vulnerable component, and there is no listening service to attack. This is LOW per noisgate: no mitigation SLA — go straight to the 365-day noisgate remediation SLA window, treat as backlog hygiene. Use the week to (1) inventory CI runners and dev workstations for the antlr4 *tool* jar / CLI, (2) add a CI guard that flags .g4 grammar files arriving from non-vendored paths without human review, and (3) document the risk-acceptance memo so when an auditor flags the vendor's 7.3 HIGH you have a one-paragraph rebuttal on file. Revisit only if vendor finally ships a patched build (none as of disclosure) or if you operate a service that compiles user-submitted grammars — in that narrow case, sandbox it and treat as MEDIUM.

Sources

  1. CVE-2026-13500 — Vulnerability-Lookup (CIRCL)
  2. CVE-2026-13501 (sibling local injection in GoTarget) — CIRCL
  3. GHSA-M64J-M5C8-F58P — Vulnerability-Lookup
  4. CWE-74: Improper Neutralization of Special Elements ('Injection') — MITRE
  5. ANTLR4 project — GitHub
  6. antlr4 npm package — Snyk advisories
  7. FIRST EPSS model
  8. CISA KEV catalog
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.