Jenkins Vulnerabilities Exploited in the Wild: CVEs and Endpoints
Which Jenkins vulnerabilities were exploited, from CVE-2024-23897 to the 2026 advisory, which endpoint each hit, and how to stop exposing Jenkins publicly.
On this page
- Jenkins security vulnerabilities that were exploited, and the endpoint each one hit
- Why exposure is the risk multiplier
- What to expose and what not to
- Step-by-step: receive webhooks without exposing Jenkins
- Hardening that still matters
- Honest limits
- More self-hosted tools that are public only for webhooks
Most Jenkins vulnerabilities that were exploited in the wild hit the CLI, the web UI or the job-configuration API, not the webhook endpoint, and an attacker can only reach them if the controller is on the public internet. Those controllers are usually public for one reason: GitHub or GitLab has to deliver a webhook. Webhook Relay's Jenkins plugin connects outward and replays only webhook deliveries, so the vulnerable surface is no longer reachable from the internet.
This is the CVE history and attack-surface view. For the full hardening checklist (authentication, agents, credentials, TLS) see Securing Jenkins.
Jenkins security vulnerabilities that were exploited, and the endpoint each one hit
Every row below links to our curated Threat Watch record, which carries the sources and timeline.
| CVE | What an attacker gets | Auth needed | Exploited in the wild | Fixed in |
|---|---|---|---|---|
| CVE-2024-23897, the Jenkins CLI file read | Arbitrary file read on the controller, chained to code execution (CVSS 9.8) | None for the first lines of a file; Overall/Read for whole files | Yes; in CISA KEV, flagged for ransomware use | 2.442, LTS 2.426.3, LTS 2.440.1 |
| CVE-2017-1000353, the remoting CLI deserialization RCE | Remote code execution via a serialized SignedObject (CVSS 9.8) | None | Yes; added to CISA KEV in 2025, no campaign named | 2.57, LTS 2.46.2 |
| CVE-2018-1000861, Stapler URL routing | Crafted URLs reach methods never meant to be web-callable; the building block of a public pre-auth RCE chain (CVSS 9.8) | None | Yes; in CISA KEV | 2.154, LTS 2.138.4, LTS 2.150.1 |
| CVE-2019-1003029, Script Security sandbox bypass | Code execution on the controller (CVSS 9.9) | Overall/Read; none if anonymous has it | Yes; in CISA KEV | Script Security 1.54 |
| CVE-2019-1003030, Pipeline: Groovy sandbox bypass | Code execution for anyone who controls a pipeline (CVSS 9.9) | Job/Configure, or a writable Jenkinsfile | Yes; in CISA KEV | Pipeline: Groovy 2.64 |
| CVE-2015-5317, Fingerprints page leak | Job and build names the viewer cannot see (CVSS 7.5) | None | Listed in KEV; we found no source describing real attacks | 1.638, LTS 1.625.2 |
| CVE-2026-117612 to 117626, the 2026-10-28 core advisory | 15 bugs: RCE for low-privilege users, file read and write, and CVE-2026-117618, a setup-wizard race that lets an unauthenticated attacker create an admin | Mostly low privilege; none for CVE-2026-117618 | No exploitation known | 2.588, LTS 2.580.2 |
Two notes on accuracy. CISA's KEV entry names CVE-2019-1003030 the "Matrix Project plugin", but the Jenkins advisory and NVD place it in Pipeline: Groovy; the Matrix Project bug in the same advisory is a different CVE. And the 2024 ransomware link is documented: BleepingComputer, citing Juniper, ties RansomEXX to a July 2024 breach of an Indian bank technology provider. The vendor advisories are 2024-01-24, 2019-03-06 and 2026-10-28.
The pattern is the point. Look at the endpoints: /cli, the remoting port, Stapler-routed UI URLs, script-check URLs and job configuration. None is /github-webhook/.
Why exposure is the risk multiplier
A flaw needing a login is a problem for insiders. The same flaw on a public controller is a problem for everyone who can run a scanner. CVE-2024-23897 needed no permission to read the first lines of a file, and the 2026 advisory includes an unauthenticated admin-creation race in the setup wizard, so a fresh controller on a reachable network is at risk. Most of the 2026 bugs need only a low-privilege account, which is easy to obtain on a controller with open sign-up or anonymous read.
Jenkins stores credentials and executes build code, so a successful bug is rarely contained to Jenkins. The Threat Watch records for the exploited CVEs give the same guidance: if the controller was reachable while running an affected version, treat it as possibly compromised and rotate the secrets it holds.
What to expose and what not to
A provider such as GitHub needs exactly one thing: a URL that accepts its webhook POST. The Jenkins plugins register these paths:
| Provider | Webhook path | Needs to be public? |
|---|---|---|
| GitHub | /github-webhook/ | Only as a delivery target |
| Bitbucket | /bitbucket-hook/ | Only as a delivery target |
| GitLab | /project/NAME | Only as a delivery target |
Everything else (UI, /cli, REST API, script-check URLs, setup wizard, agent port) | n/a | No |
See the complete Jenkins webhook URL reference for the exact forms. The goal is that the public side is a Webhook Relay bucket URL, and Jenkins keeps no public address at all.
Step-by-step: receive webhooks without exposing Jenkins
The primary path is the Webhook Relay Jenkins plugin, documented at the Jenkins plugin tutorial. It needs Jenkins 2.479.1 or newer and a Webhook Relay account with an API token.
- Install the plugin. In Manage Jenkins → Plugins → Available, search for Webhook Relay and install it.
- Configure the connection. In Manage Jenkins → System, open the Webhook Relay section. Enter your API Key and API Secret, a bucket name (an existing one, or a new name the plugin creates), pick the SCM Webhook Preset (GitHub, GitLab, Bitbucket or Generic Webhook Trigger), tick Enable and save. Connection Status should read Subscribed.
- Get the public URL. Click Get Webhook URL. The plugin resolves the bucket's public input URL.
- Point the provider at it. GitHub: Settings → Webhooks → Add webhook → Payload URL, content type
application/json. GitLab: Settings → Webhooks → URL. Bitbucket: Repository settings → Webhooks → Add webhook → URL. - Configure the job normally. For GitHub, enable GitHub hook trigger for GITScm polling (
githubPush()in a declarative pipeline). - Close the inbound path. Remove the port forward, public DNS record or reverse-proxy rule that made Jenkins reachable.
The plugin subscribes over a persistent outbound WebSocket and replays each delivery to the Jenkins endpoint for your SCM (/github-webhook/, /bitbucket-hook/, or /project/NAME for GitLab). No inbound ports are opened on Jenkins. The flow is GitHub → bucket URL → outbound WebSocket → /github-webhook/.
If you prefer a standalone agent, the Jenkins and GitHub tutorial uses the CLI:
relay forward --bucket github-jenkins http://localhost:8080/github-webhook/ --no-agent
Lock the destination path. By default an output appends any extra path the sender adds to the input URL (a POST to <input URL>/anything goes to <destination>/anything). Outputs created in the dashboard have Destination URL path locked switched on; outputs created with the CLI or API do not, so open the output and turn it on (API/MCP field lock_path: true). With the path locked, every delivery goes to exactly the destination URL and nothing else on Jenkins is reachable through the relay. The plugin path above needs no extra step: with no output on the bucket it always delivers to the preset endpoint.
It prints a *.hooks.webhookrelay.com URL for your provider; run the agent as a Docker container or a background service so it reconnects after restarts. The general pattern is in receiving webhooks on localhost. Either way, deliveries appear on the bucket's logs page with the response Jenkins returned.
Hardening that still matters
Removing exposure does not make Jenkins safe; it removes the cheapest attack route.
- Patch. Upgrade to 2.588 or LTS 2.580.2 and keep Script Security and Pipeline: Groovy current. Most of the CVEs above are years old, which means forgotten Jenkins hosts are the real target.
- Authenticate. Remove Overall/Read from anonymous and keep sign-up off. The checklist is in Securing Jenkins.
- Verify signatures at the relay. The public bucket URL is still a URL anyone can post to. Attach an HMAC verification function to the bucket input and Webhook Relay checks GitHub's
X-Hub-Signature-256before anything is forwarded: requests without a valid signature get a 401 at the relay and never reach Jenkins. You can also keep a shared secret in Jenkins (GitHub section, Advanced, Shared secrets), as the Jenkins and GitHub tutorial shows, as a second check. For the details, read how to verify a webhook signature and webhook security best practices. - Filter. A forwarding rule or function on the bucket can drop events you never build on, such as pushes to other branches, so Jenkins never sees them. See webhooks in CI/CD for the wider pattern.
Honest limits
The relay is not a patch, and it does not help in these cases:
- A flaw in the webhook handler itself. The relay forwards webhook traffic to it by design. With signature verification at the relay, only requests your provider signed get that far, so an anonymous attacker cannot reach the handler at all. What remains is attacker-controlled content inside a genuine delivery, such as a branch name or pull request title. Patching fixes that.
- Users who need the UI from outside. The relay carries webhooks, not logins. Put the UI behind a VPN or identity-aware proxy.
- Agents and workers connecting from outside. Inbound agent connections need their own private network path.
- Insiders and compromised networks. Anyone already inside can still reach
/cli. - Controllers already breached. Closing the door after a compromise does not undo it; rotate credentials and rebuild.
