CVE-2024-23897 — Jenkins args4j arbitrary file read

CVE-2024-23897 — Jenkins args4j arbitrary file read

TL;DR: Jenkins’ CLI parser uses the args4j library, which by default expands @filename arguments into the file’s contents. Anonymous or low-privilege users could send a CLI command with an @ argument and have Jenkins read arbitrary files on the master — including the secrets directory. With Overall/Read or anonymous-enabled instances, the bug went from “info disclosure” to “RCE via stolen secret + cred-based command”. Disclosed January 2024; mass-exploited within days. Companion to jenkins-attacks and reading-public-pocs-effectively.

Why this is a great study target

  • The root cause is a library defaultargs4j had @filename expansion on by default.
  • The patch is two lines — disable the expansion.
  • The exploit is trivial to write once you know the primitive.
  • The chain to RCE depends on instance state, making it a good exercise in turning info-disclosure into impact.

The args4j default

args4j (Kohsuke Kawaguchi, who is also the Jenkins founder) supports expansion of @filename into the file’s contents at parse time. Many Jenkins CLI commands take args4j-parsed parameters. With anonymous access, a remote unauthenticated user could send:

1
java -jar jenkins-cli.jar -s https://target/ help "@/etc/passwd"

…and have the contents of /etc/passwd echoed in the error response (the parser tried to interpret the contents as a command name).

The same primitive applied to /var/jenkins_home/secrets/master.key and the secrets/*.key files, which protect Jenkins’ credentials store.

The patch

args4j calls were guarded by an explicit flag to disable @filename expansion. The fix sets that flag for every CLI command parse.

That’s it. The fix is a one-bit default.

From file read to RCE

Two common chains:

Chain A — anonymous + secrets

  1. Read secrets/master.key and secrets/hudson.util.Secret.
  2. Use these to decrypt credentials stored in credentials.xml.
  3. Use a decrypted credential (cloud token, agent SSH, deploy key) for further compromise.

Chain B — authenticated low-priv user

If Overall/Read is granted (common when SSO is on):

  1. Read the same secrets.
  2. Or — read source for installed plugins → find a sink reachable from Overall/Read → escalate to RCE inside Jenkins.

Read sessions / API tokens of administrators, replay to call admin endpoints.

The exploit

The minimum trigger is one line:

1
java -jar jenkins-cli.jar -s https://target/ help "@FILE"

But many programs ship a Python or HTTP-only variant of the CLI protocol; the bug worked across all entry-point variants. PoCs hit the /cli HTTP endpoint directly with raw protocol bytes.

After disclosure, public PoCs (Nuclei templates, GitHub repos) appeared the same day. Mass scanners hit internet-exposed Jenkins instances quickly.

Detection

  • Jenkins logs the CLI command name; an @ at position 0 of an arg is a strong indicator.
  • Egress logs of Jenkins → outbound HTTP from secret-derived creds.
  • Filesystem access logs (if auditd configured) showing jenkins user reading /etc/passwd or non-typical paths.

Affected versions

  • Jenkins core 2.441 and earlier.
  • LTS 2.426.2 and earlier.

Fixed in 2.442 / LTS 2.426.3.

Lessons

  • Library defaults can be CVEs. Audit dependency defaults, especially ones with file-read implications.
  • Anonymous-by-default Jenkins is still common in dev / lab environments. CI/CD admin should treat any exposure as breach-equivalent.
  • Secrets in-band with the application are a single-bug-from-RCE design. Hardware security modules or external secret managers reduce blast radius.
  • CI/CD compromise chains into the production environment. See ci-cd-as-cloud-attack-surface.

Reproducing in a lab

  1. Pull Jenkins 2.441 via Docker.
  2. Disable any authentication realm (anonymous read).
  3. Run the cli with @-prefixed argument.
  4. Observe file contents echoed in the error.
  5. Decrypt a stored credential using the leaked master.key and hudson.util.Secret.

The Jenkins community published step-by-step in their advisory.

  • CVE-2018-1000861 (Jenkins remote code execution via Stapler).
  • CVE-2017-1000353 (Jenkins serialised pre-auth).
  • Pattern: CLI + plugin endpoints keep accumulating critical issues. Worth a dedicated audit.

References