This is like reporting that a C compiler can compile malicious code and calling it a remote exploit
CVE-2026-13500 targets tool/src/org/antlr/v4/codegen/model/OutputFile.java in ANTLR4 versions 4.13.0 through 4.13.2. ANTLR4 is a parser generator — a *build-time developer tool* that reads .g4 grammar files and emits source code in a target language (Java, Python, C#, etc.). Grammar files support action blocks: inline snippets of target-language code that get embedded verbatim into the generated output. The "vulnerability" is that a malicious .g4 file can contain arbitrary code in these action blocks, which then appears in the generated source. If that generated source is compiled and executed, the injected code runs. Affected versions are 4.13.0, 4.13.1, and 4.13.2. No fix exists or is planned — the ANTLR4 maintainers have stated this is a core design feature that cannot be removed without breaking the tool entirely.
The vendor CVSS 3.1 score of 7.3 HIGH with vector AV:N/AC:L/PR:N/UI:N is grossly misleading. There is no network service, no listener, no unauthenticated remote entry point. The attack requires an adversary to social-engineer a developer into processing a trojanized grammar file, or to compromise a source repository — then the generated code must be compiled and executed. This is functionally identical to a supply-chain trojan (like a malicious Makefile or poisoned dependency), not a remotely exploitable vulnerability. Notably, CVSS 4.0 already corrects downward to 6.9 MEDIUM, and the ANTLR4 maintainers themselves say the practical risk is "close to null." Rundeck, a major downstream consumer, formally assessed this as a false positive because they only ship antlr4-runtime (not the code-generation tool). The 7.3 HIGH label will generate scanner noise across your fleet for a risk that requires a multi-step supply-chain attack against a developer tool.
4 steps from start to impact.
Craft a trojanized .g4 grammar file
.g4) with malicious target-language code embedded in action blocks (@header, @members, or inline {...} actions). These blocks accept arbitrary code by design — there is no sanitization because that is the intended feature. The malicious grammar must be syntactically valid to pass ANTLR4's own parser.- Attacker must understand ANTLR4 grammar syntax and action block semantics
- Attacker must know the target language (Java, Python, C#, etc.) of the victim's code generation pipeline
- Crafting a convincing grammar requires domain knowledge of the victim's parser project
- A grammar with suspicious action blocks is detectable via code review or diff inspection
.g4 files. Standard SAST tools do not parse ANTLR4 grammars.Deliver the grammar to the victim's build environment
.g4 file must reach a location where the ANTLR4 tool will process it. Delivery vectors include: pull request to an open-source grammar repository, typosquatted grammar package, compromised internal repo, or direct social engineering (e.g., 'here is a grammar for your new DSL'). This is a supply-chain insertion step, not a network exploit.- Attacker must have write access to a grammar source the victim trusts, OR must social-engineer a developer into using the file
- The victim must be using the
antlr4-tool(code generator), not justantlr4-runtime
- Most enterprises version-control grammars in private repos with access controls and code review
- Open-source grammar repos (antlr/grammars-v4) have maintainer review
- Most ANTLR4 consumers only use
antlr4-runtime— the tool is only used at grammar-authoring time
ANTLR4 tool generates source with injected code
antlr4 (via CLI, Maven plugin antlr4-maven-plugin, or Gradle plugin) against the malicious grammar, the tool faithfully transcribes action block content into the generated .java/.py/.cs source files. This step is automatic and produces no warnings — the tool is working as designed.- The
antlr4-toolmust be invoked against the malicious grammar file - The build system must be configured to run ANTLR4 code generation
- Developer reviewing generated source diffs would see injected code
- CI pipelines that diff generated output against a baseline would flag changes
Runtime.exec(), os.system()), but this is not standard practice for ANTLR-generated code.Generated code is compiled and executed
- Generated source must pass compilation (it will, since action blocks contain valid target-language code)
- The compiled artifact must be executed — in tests, CI, or production
- Multiple human and automated review gates typically exist between grammar change and production deployment
- The blast radius is limited to the build environment or the specific application using the generated parser
antlr4-runtime only — the runtime parses input against pre-generated code and is not affected. If your SCA scanner flags antlr4 as a dependency, check whether it's the antlr4-maven-plugin, antlr4-tool jar, or antlr4-runtime. If runtime-only, suppress the finding. No mitigation SLA applies for LOW — treat as backlog hygiene..g4 grammar files are committed to your SCM with code-review requirements (CODEOWNERS, branch protection). Never pull grammars from external sources at build time without pinning to a reviewed commit hash. This eliminates the supply-chain delivery vector entirely.git diff --exit-code on generated directories.antlr4 in CI, execute it inside a sandboxed container with no network access and minimal filesystem permissions. Even if malicious code is injected and compiled, it cannot exfiltrate data or pivot. Standard practice for build isolation.- Upgrading ANTLR4 — no fix exists or is planned. The behavior is by design. Upgrading to a hypothetical future version will not change this, as the maintainers have explicitly stated they will not remove action block support.
- WAF or network-layer controls — there is no network attack surface. ANTLR4 is a local CLI tool. Network controls are completely irrelevant.
- Vulnerability scanning / SCA suppression alone — suppressing the scanner finding without verifying whether you use
antlr4-toolvsantlr4-runtimeleaves you uncertain. Verify first, then suppress.
The supporting signals.
| In-the-wild exploitation | None observed. Not listed on CISA KEV. No reports of active campaigns targeting ANTLR4 grammar processing. The ANTLR4 maintainers explicitly state practical risk is "close to null." |
|---|---|
| Proof-of-concept | A public PoC exists at wooyun123/wooyun#4, demonstrating malicious action block injection. The PoC is trivial — it's literally writing code in a grammar action block, which is the tool's intended function. No weaponized exploit chain exists. |
| EPSS | 0.00516 (0.42nd percentile) — in the bottom half of all scored CVEs. FIRST's model considers exploitation extremely unlikely. |
| KEV status | Not listed. No indication of addition pending. |
| CVSS vectors | CVSS 3.1: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L → 7.3 HIGH. CVSS 4.0: 6.9 MEDIUM. The AV:N (Network) and UI:N (No User Interaction) components are factually incorrect — there is no network service and the attack absolutely requires user interaction (processing a malicious grammar file). |
| Affected versions | ANTLR4 4.13.0, 4.13.1, 4.13.2. Only the antlr4-tool component is affected — antlr4-runtime (the library most consumers ship) is not affected. |
| Fixed versions | None. No fix planned. ANTLR4 maintainers have stated the behavior is by design and cannot be removed without breaking the core action-block feature. Downstream vendors (Rundeck, etc.) have assessed this as a false positive. |
| Scanning / exposure data | No network exposure. ANTLR4 is a build-time tool, not a network service. Shodan/Censys/GreyNoise have zero relevance. Scanner noise will come from SCA tools flagging the antlr4 dependency in Maven/Gradle/pip manifests. |
| Disclosure timeline | Disclosed 2026-06-28 via VulDB (VulDB #374495). Vendor contacted early but "did not respond in any way" per VulDB's disclosure note. ANTLR4 maintainers later clarified their position that this is intended behavior. |
| Reporter | Attributed to wooyun123 via the GitHub issue. No affiliation with a major security research organization disclosed. |
Sources.
Why this verdict
- Misclassified attack vector: The CVSS vector claims AV:N/AC:L/PR:N/UI:N, but there is no network service. The attack requires delivering a malicious
.g4file to a developer's build environment and having them process it — this is a supply-chain/social-engineering prerequisite, not an unauthenticated remote exploit. Correcting to AV:L/AC:H/PR:N/UI:R alone drops the base score below 5.0. - Multi-step supply-chain chain with compounding friction: The attack requires (1) crafting a malicious grammar, (2) getting it accepted into a trusted source, (3) having the ANTLR4 *tool* (not runtime) process it, and (4) compiling and executing the output. Each step has independent friction: code review, SCM access controls, build pipeline diffing, and SAST scanning of generated code.
- Vendor confirms by-design behavior: The ANTLR4 maintainers explicitly state this is a core design feature (action blocks are *supposed* to contain arbitrary target-language code) and will not issue a fix. This is the parser-generator equivalent of saying 'gcc can compile malicious C code.' Multiple downstream vendors (Rundeck) have formally assessed this as a false positive.
- Role multiplier: ANTLR4 tool is a *build-time developer utility*, not a production service. (a) Dev workstation (primary role, ~70% of installs): local-only impact, blast radius limited to one developer's machine. (b) CI/CD pipeline (~25% of installs): the tool runs in CI to regenerate parsers, but grammars are version-controlled with review gates; blast radius bounded to the CI runner. (c) Production runtime (<5%): only
antlr4-runtimeships to production, and the runtime is NOT affected by this CVE. No high-value-role floor applies — the affected component is not an IdP, hypervisor, DC, PAM, backup, edge appliance, or any canonical high-value role. The worst plausible outcome is code execution on a CI runner or developer workstation, which is a local/host-level blast radius. - EPSS confirms negligible exploitation likelihood: At 0.00516 (0.42nd percentile), FIRST's empirical model rates this among the least likely CVEs to be exploited. No KEV listing, no campaign reports, no threat intel attributions.
Why not higher?
While the PoC is public and trivial to reproduce, every step of the attack chain requires prior access or social engineering that compounding friction makes impractical at scale. The affected component (antlr4-tool) is a build-time utility, not a production service — it never listens on a network port, never processes untrusted input in normal operation, and the vast majority of ANTLR4 consumers only ship antlr4-runtime (which is unaffected). There is no high-value-role deployment pattern that would floor this above LOW.
Why not lower?
An IGNORE verdict would be inappropriate because the CVE is technically valid — a malicious grammar file *can* inject code into generated output, and CI/CD pipelines that process grammars from semi-trusted sources (e.g., open-source grammar repos pulled at build time) do have a narrow but real attack surface. A 2.5 LOW acknowledges this theoretical supply-chain risk while reflecting the enormous practical friction.
Crowdsourced verification payload.
Run this script on any build host or CI runner where ANTLR4 may be used. It checks Maven, Gradle, and pip environments for the presence of the affected antlr4-tool component (not the runtime). Requires read access to project directories. Invoke with: bash check_cve_2026_13500.sh /path/to/project
#!/usr/bin/env bash
# CVE-2026-13500 Checker — ANTLR4 Tool (not runtime) presence & version
# Usage: bash check_cve_2026_13500.sh /path/to/project
# Exit codes: 0=PATCHED/NOT_AFFECTED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
PROJECT_DIR="${1:-.}"
VULN_VERSIONS="4\.13\.[012]"
FOUND_TOOL=0
FOUND_VULN=0
echo "[*] CVE-2026-13500: Checking for antlr4-tool in $PROJECT_DIR"
# Check Maven pom.xml for antlr4-maven-plugin
while IFS= read -r -d '' pomfile; do
if grep -q 'antlr4-maven-plugin' "$pomfile" 2>/dev/null; then
FOUND_TOOL=1
ver=$(grep -A5 'antlr4-maven-plugin' "$pomfile" | grep -oP '(?<=<version>)[^<]+' | head -1)
if [[ -n "$ver" ]] && echo "$ver" | grep -qP "^${VULN_VERSIONS}$"; then
echo "[!] VULNERABLE: $pomfile uses antlr4-maven-plugin version $ver"
FOUND_VULN=1
elif [[ -n "$ver" ]]; then
echo "[+] $pomfile uses antlr4-maven-plugin version $ver (check manually)"
else
echo "[?] $pomfile references antlr4-maven-plugin but version not parsed"
fi
fi
done < <(find "$PROJECT_DIR" -name 'pom.xml' -print0 2>/dev/null)
# Check Gradle build files for antlr4 plugin or tool dependency
while IFS= read -r -d '' gradlefile; do
if grep -qE '(antlr4|org\.antlr.*antlr4.*:4\.)' "$gradlefile" 2>/dev/null; then
# Skip runtime-only references
if grep -qE 'antlr4-runtime' "$gradlefile" && ! grep -qE 'antlr4[^-]' "$gradlefile"; then
echo "[+] $gradlefile uses antlr4-runtime only — NOT AFFECTED"
continue
fi
FOUND_TOOL=1
ver=$(grep -oP 'antlr4[^-].*?:([0-9.]+)' "$gradlefile" | grep -oP '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
if [[ -n "$ver" ]] && echo "$ver" | grep -qP "^${VULN_VERSIONS}$"; then
echo "[!] VULNERABLE: $gradlefile uses antlr4 tool version $ver"
FOUND_VULN=1
elif [[ -n "$ver" ]]; then
echo "[+] $gradlefile uses antlr4 version $ver (check manually)"
else
echo "[?] $gradlefile references antlr4 but version not parsed"
fi
fi
done < <(find "$PROJECT_DIR" -name '*.gradle' -o -name '*.gradle.kts' -print0 2>/dev/null | tr '\n' '\0')
# Check pip / Python environments
if command -v pip &>/dev/null; then
pipver=$(pip show antlr4-tools 2>/dev/null | grep -i '^Version:' | awk '{print $2}')
if [[ -n "$pipver" ]]; then
FOUND_TOOL=1
if echo "$pipver" | grep -qP "^${VULN_VERSIONS}$"; then
echo "[!] VULNERABLE: pip antlr4-tools version $pipver"
FOUND_VULN=1
else
echo "[+] pip antlr4-tools version $pipver (check manually)"
fi
fi
fi
# Check for standalone antlr4 jar
while IFS= read -r -d '' jarfile; do
if [[ "$jarfile" == *antlr4-4.13.[012]* ]] && [[ "$jarfile" != *runtime* ]]; then
echo "[!] VULNERABLE: Found antlr4-tool jar: $jarfile"
FOUND_TOOL=1
FOUND_VULN=1
fi
done < <(find "$PROJECT_DIR" -name 'antlr4-*.jar' -print0 2>/dev/null)
if [[ $FOUND_VULN -eq 1 ]]; then
echo ""
echo "VULNERABLE — antlr4-tool 4.13.0-4.13.2 detected."
echo "NOTE: No vendor fix exists. Verify grammar files are from trusted, reviewed sources."
exit 1
elif [[ $FOUND_TOOL -eq 0 ]]; then
echo ""
echo "PATCHED — No antlr4-tool dependency found (antlr4-runtime only is NOT affected)."
exit 0
else
echo ""
echo "UNKNOWN — antlr4-tool found but version could not be confirmed as vulnerable."
exit 2
fi