Jenkins Script Console RCE: Notes for Careful Bug Bounty Tests
Jenkins Script Console is intentional remote code execution for administrators. The bounty question is never "can Groovy run?" It is "who can reach it, and did auth fail?"
Treat every test as if the controller builds production.
Find the console and the auth gate
Common paths:
/script/scriptText- agent-related consoles on some setups
- Plugin endpoints that evaluate expressions
Unauthenticated 200 on /script with a Groovy form is a critical misconfig. Authenticated access for a low-priv user—builder, anonymous read plus an overlooked overall/runScripts—is the same class of bug with a different login story.
Check also:
- Signup enabled with default permissions that include script approval powers
- CSRF crumbs missing on
scriptText - Old plugin CVEs that expose similar evaluation (document version; do not weaponize blindly)
Fingerprint with /login branding, X-Jenkins headers, and /whoAmI. Matrix Authorization and Role-based plugins change which permission name you must cite. Screenshot the permission that granted script access; "I got RCE" without the ACL path frustrates triage.
Reverse proxies sometimes expose /script while the main UI sits behind SSO. Test the raw path on the same host even when the homepage redirects to Okta. That split personality is how anonymous consoles survive "we enforced SSO" rollouts.
Prove code execution without becoming the outage
Do not run shutdown(), mass delete jobs, or curl reverse shells to random VPS hosts. Prefer a read-only Groovy snippet that prints a canary:
println "bugflare-canary-7f3a"
Or read a harmless system property. Capture the response showing your canary. That is RCE for severity purposes.
If the console is blocked but you have job configuration rights, remember pipeline script blocks and poorly sandboxed shared libraries. Those are adjacent findings; keep them separate so triage can route them.
I've seen hunters lose reports because they "proved" access by creating twenty jobs. One canary print is enough.
When CSRF protection is on, show the crumb flow you used. When it is off, that is part of the bug. Either way, keep payloads tiny and idempotent.
Context that raises or lowers severity
Note whether Jenkins runs as a high-priv OS user, whether agents are attached, and whether credentials bindings are visible in the UI. Credential theft via script console is often the real business impact; mention the API methods you could call, then stop.
Anonymous read of job configs may leak repo tokens in plaintext build steps. That can stand alone even when /script is locked.
Controller vs agent matters. Script console on the controller is usually worse than a locked-down agent shell. If you only reached an ephemeral agent, say so and adjust severity honestly.
Report and remediations
Give URL, auth bypass or role used, exact Groovy (canary only), Jenkins version, and a sentence on host impact. Recommend locking down Overall/RunScripts, disabling anonymous access, enabling CSRF protection, isolating the controller network, and upgrading plugins on a schedule.
Jenkins security docs stress controller hardening for a reason: this process is a crown jewel. Write the report like you are helping the admin who owns on-call, not like you are auditioning a malware sample.