← All field notes
ci/cdcredential theftfor responders

Jenkins credential store dump: one job binds the whole chest

A Jenkins job with configure access can bind the entire credential store and exfiltrate it. The principal is the set of stored secrets, so you rotate the whole store and the downstream keys it protected.

The Jenkins credential store is a single chest holding the keys to cloud accounts, registries, and SSH targets. Any job with the right access can ask for those keys, and masking only hides them in the log.

How the attack works

An attacker with job-configure or pipeline-edit access reconfigures a job to wrap a step in withCredentials referencing many credential IDs, or uses the Script Console to enumerate and decrypt the store. The build binds the credentials into environment variables and writes or transmits them, defeating log masking, and the decrypted cloud keys, registry logins, and SSH keys are posted off-platform. A stolen cloud key is then used against systems Jenkins normally deploys to. In ATT&CK terms this is T1552, Unsecured Credentials, with T1213, Data from Information Repositories, and T1648 for the build execution.

Why it works

withCredentials and the Script Console are legitimate features. The tell is scope and intent: a normal build binds the one or two credentials its task needs, while this one binds an unusually large set of unrelated secrets, or enumerates the whole store, and exfiltrates them. Broad configure access plus a shared long-lived store any job can bind from is the root cause.

How to fix it

Once a build bound and transmitted the store, those credentials are out, so rotate every credential in the store, revoke agent and build tokens, and rotate the downstream keys those credentials protected. Deleting the job or re-masking the log changes nothing. Forensics spans two surfaces: Jenkins audit and build logs show which IDs were bound, and the downstream systems’ audit logs show where the keys were used. For the class, restrict job-configure and Script Console to least privilege, scope credentials per folder or job, and prefer short-lived just-in-time credentials.

Practice it

We built this as a GraphLattice Range scenario so responders can rehearse rotating the whole store and its downstream keys, then scoping the blast radius.