Skip to content

Jenkins Secrets, Explained: What the Credentials Plugin Gets Wrong

Jenkins Secrets Management Guide

Key Takeaways

Jenkins’ Credentials Plugin encrypts secrets at rest, but the design is decryptable: anyone with Script Console access can run Groovy code to decrypt any stored credential, and the master key that protects everything else sits unencrypted on the filesystem.

The native plugin also has no automated rotation, no audit trail of who accessed which secret and when, and no way to issue short-lived, dynamic credentials.

In GitGuardian’s 2026 analysis of a major CI/CD supply-chain attack, 59% of the compromised machines were CI/CD runners rather than developer laptops, a sign that pipelines are now a primary credential-theft target.

Fixing these shortcomings means scoping every credential to the narrowest job that needs it, excluding the secrets directory from backups, and moving production secrets to a dedicated secrets manager that issues short-lived credentials instead of storing static ones.

Akeyless’s native Jenkins plugin retrieves static, dynamic, and rotated secrets, plus issues PKI and SSH certificates, directly into pipelines, removing the need to store long-lived credentials in Jenkins at all.

Quick Answer: How Do You Manage Secrets Securely in Jenkins?

Jenkins’ built-in Credentials Plugin encrypts secrets but can’t rotate them automatically, can’t stop a Script-Console-privileged admin from decrypting them, and keeps no audit trail; production pipelines need a dedicated secrets manager that issues short-lived, auditable credentials instead.

  • Never rely on Jenkins’ native credential store alone for production secrets.
  • Scope every credential to the specific job or folder that actually needs it, not globally.
  • Replace long-lived static secrets with dynamic ones issued at pipeline runtime through a secrets manager plugin.

Quick Facts

CategoryData Point
Secrets sprawl28.65 million new hardcoded secrets were added to public GitHub commits in 2025, a 34% increase year over year (GitGuardian State of Secrets Sprawl 2026)
CI/CD as the breach surface59% of machines found compromised in GitGuardian’s Shai-Hulud 2 dataset analysis were CI/CD runners, not personal workstations (GitGuardian State of Secrets Sprawl 2026)
Jenkins-specific exposureMore than 70 security vulnerabilities were disclosed in Jenkins in 2025 alone, most tied to plugins (CVE.org records, via JetBrains TeamCity blog)
Still unpatchedOver 45,000 internet-exposed Jenkins servers remained vulnerable to CVE-2024-23897, per a Shadowserver Foundation scan JetBrains cited in its March 2026 analysis (JetBrains TeamCity blog)
Remediation lagAt least 64% of secrets confirmed valid in 2022 were still active and exploitable when GitGuardian retested them in January 2026 (GitGuardian State of Secrets Sprawl 2026)

Jenkins needs credentials for nearly everything it touches, and how it stores those credentials determines whether a single compromised pipeline becomes a minor incident or a full breach.

Jenkins pipelines pull code from private repositories, push Docker images to registries, and deploy to production, and every one of those steps runs on a credential Jenkins is holding somewhere.

Most teams reach for the built-in Credentials Plugin first, and for good reason: it is already installed, already integrated with pipelines, and far better than pasting an API key into a Jenkinsfile. But “better than nothing” and “secure enough for production” are different bars, and Jenkins’ native credential store doesn’t clear the second one on its own, especially as secrets sprawl across more pipelines and more tools.

The rest of this guide covers how Jenkins stores secrets today, where the native model breaks down, and what a practical path to production-grade secrets management actually looks like.

What Is Jenkins Secrets Management, and How Does It Work Natively?

Jenkins’ Credentials Plugin stores secrets in an encrypted format on the Jenkins controller. It makes them available to jobs and pipelines without exposing them in logs or console output.

Jenkins organizes credentials along two dimensions: type and scope. The plugin supports five main credential types: secret text for API tokens and webhook secrets, username-and-password pairs for basic authentication, secret files for certificates and configuration data, SSH keys for Git and remote-agent connections, and X.509 certificates for mutual TLS. Every credential is also stored at one of two scopes: System, which limits it to Jenkins configuration and plugins, or Global, which makes it available to jobs and pipelines as well. Many folder-based setups add a third layer, scoping credentials to a specific folder and its child jobs.

Under the hood, Jenkins encrypts these values with AES in cipher block chaining mode, storing the encryption keys in the $JENKINS_HOME/secrets/ directory, per Jenkins’ own developer documentation.

How Do You Add and Use Secrets in a Jenkins Pipeline?

Adding a secret in Jenkins takes a few clicks in the UI, but using it safely inside a pipeline depends on one specific syntax pattern.

To add a credential, open Manage Jenkins → Credentials, select the appropriate scope, and click Add Credentials. Choose a type and give it a unique, descriptive ID rather than a generic one like “password.” To use the credential inside a Jenkinsfile, the withCredentials step injects it as an environment variable for the duration of the block and masks it from console output:

pipeline {
    agent any
    stages {
        stage('Build and Push Docker Image') {
            steps {
                withCredentials([
                    usernamePassword(
                        credentialsId: 'dockerhub-credentials',
                        usernameVariable: 'DOCKER_USER',
                        passwordVariable: 'DOCKER_PASS'
                    )
                ]) {
                    sh '''
                        echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
                        docker build -t myapp:${BUILD_NUMBER} .
                        docker push myapp:${BUILD_NUMBER}
                    '''
                }
            }
        }
    }
}

Why Native Jenkins Credentials Aren’t Secure Enough for Production

Jenkins encrypts credentials at rest, but the encryption is decryptable by design. Anyone with Script Console access can run a few lines of Groovy and recover any stored credential in plain text.

Jenkins protects secrets with a three-file chain: credentials.xml holds the encrypted values, hudson.util.Secret decrypts those values, and master.key decrypts hudson.util.Secret. The problem is master.key itself is stored unencrypted on the controller’s filesystem, a fact Jenkins’ own security documentation confirms directly. An administrator with access to the Script Console (Manage Jenkins → Script Console) can run hudson.util.Secret.decrypt() against any encrypted value and get the plain text back. Multiple security researchers have documented the Script Console decryption technique independently, including a widely cited Codurance write-up that walks through dumping every credential on a Jenkins instance the same way. Anyone who can create jobs on the instance and reference a Global-scoped credential effectively has the same plaintext-decryption access, since a pipeline job can be written to extract the credential the same way. Global scope is what makes that job-level extraction possible: it’s what makes a credential available to any job on the instance in the first place.

The three-file decryption chain — credentials.xml → hudson.util.Secret → master.key — is Jenkins’ documented architecture, not a misconfiguration. master.key sits unencrypted on disk by design, which is what makes Script Console decryption possible.

Beyond the architectural flaw, native Jenkins credentials fall short in three operational ways that matter at production scale, and the same three problems show up across CI/CD pipelines generally, not just Jenkins. There is no built-in automated rotation, so every credential update is a manual, per-job task. There is no audit trail showing who accessed which secret or when. And everything is static, with no way to issue a short-lived credential that expires on its own.

A Practical Checklist for Securing Jenkins Secrets

Securing Jenkins secrets means fixing some things immediately and rebuilding others into the architecture permanently.

Immediate fixes: restrict $JENKINS_HOME/secrets/ to chmod 0700 and exclude it from backups, per Jenkins’ own security documentation. Scope every credential to the lowest working level, job or folder rather than System or Global, instead of granting broad access by default. Give credentials descriptive, unique IDs instead of generic ones. Put Jenkins behind a VPN rather than exposing it to the public internet: Shadowserver’s scans have repeatedly found tens of thousands of internet-exposed Jenkins servers still vulnerable to known CVEs, evidence that publicly reachable instances get actively targeted.

Long-term fixes: move production secrets out of Jenkins’ native store and into a dedicated secrets management platform issuing dynamic, short-lived credentials at runtime, a practice central to enforcing zero-trust architecture. Automate rotation instead of doing it manually. Centralize audit logging so secret access is visible outside of Jenkins itself, not just inside it.

Comparing Approaches to Jenkins Secrets Management

Every approach to Jenkins secrets trades setup effort for risk reduction. The lowest-risk approaches remove standing, storable credentials entirely, moving from static to rotated to dynamic secrets as pipeline risk goes up.

ApproachHow It WorksRotationAudit Trail
Native Credentials PluginSecrets encrypted at rest on the controller, injected via withCredentialsManualNone built in
External vault plugin (e.g., HashiCorp Vault)Jenkins authenticates to an external vault and fetches secrets at pipeline runtimeDepends on vault configurationProvided by the external vault
Dedicated secrets-manager plugin with dynamic secretsJenkins fetches static, dynamic, or rotated secrets and certificates from a SaaS secrets manager at runtimeAutomated, policy-drivenCentralized, outside Jenkins

Is a Secrets Manager Alone Enough?

Moving secrets out of Jenkins’ native store solves the decryption and rotation problems. It doesn’t automatically solve credential scoping or certificate lifecycle management on its own.

A dedicated secrets manager fixes how credentials are stored and delivered. But a Jenkins pipeline often needs more than passwords and API tokens. It needs SSH keys signed for a specific user and PKI certificates issued for mutual TLS through certificate lifecycle management, both scoped and audited the same way secrets are. A secrets manager handling only static or dynamic secrets still leaves certificate issuance as a separate, manually managed problem.

How Akeyless Secures Jenkins Secrets and Certificates

The Challenge

Replacing Jenkins’ native credential store solves half the problem; the other half is issuing and rotating the certificates a pipeline needs without adding a second, disconnected tool.

The Approach

Akeyless‘s native Jenkins plugin retrieves static, dynamic, and rotated secrets and issues PKI and SSH certificates directly into pipelines. It supports eight authentication methods per the plugin’s official documentation: API Key, AWS IAM, Azure AD, Certificate, GCP, Kubernetes, Universal Identity, and Email. Configuration happens through the plugin’s Path, Environment Variable, and Key Name fields in either the Freestyle Environment section or Pipeline job configuration, as part of the same CI/CD integration set Akeyless ships for DevOps tooling generally.

The Outcome

The result is a pipeline where secrets and certificates both come from the same governed source instead of two separate systems with two separate audit trails.

withAkeyless(
    configuration: [
        akeylessCredentialId: 'akeyless-prod-auth',
        akeylessUrl: 'https://your-gateway-url/api/v2'
    ],
    akeylessSecrets: [[
        path: '/jenkins/dockerhub-credentials',
        secretValues: [[secretKey: 'data', envVar: 'DOCKER_CREDS']]
    ]]
) {
    sh 'echo $DOCKER_CREDS | docker login --username user --password-stdin'
}
The Akeyless Jenkins plugin retrieves Static, Dynamic, and Rotated secrets plus PKI and SSH certificates, a broader scope than most Jenkins secrets guides account for, which typically stop at secret injection.

How Enterprises Already Trust Akeyless With Credential Management

Neither Progress’s case study nor Cimpress’s names Jenkins specifically, but both describe the same operational shift this guide recommends for Jenkins pipelines: moving off manual, static credential handling and onto centrally governed secrets management.

Progress Software, a global software company operating in 16 countries, adopted Akeyless to fight secrets sprawl across a multi-cloud environment inherited through acquisitions. Their published case study credits “frictionless DevOps integration,” citing fast adoption “with no code changes” and CI/CD pipelines connecting “instantly with no rework or delays.” Richard Barretto, Chief Information Security Officer and VP at Progress, put it simply: “Akeyless is true SaaS that allows you to scale. It’s purpose-built to live in the cloud. We saved 70% of our maintenance and provisioning time with Akeyless.”

Cimpress’s experience points at the other half of the equation, credential rotation specifically. Conor Mancone, Principal Application Security Engineer at Cimpress, described the shift away from manual rotation directly: “We set Akeyless up nine months ago and we haven’t had to worry about credential rotation. We haven’t had to worry about credential leakage. All of our software that’s running, it just works, we haven’t really had to think about it since then.” Cimpress’s deployment isn’t Jenkins-specific either, but the underlying problem is exactly what a Jenkins pipeline runs into once enough services depend on it: static credentials someone has to remember to rotate.

How Do You Choose the Right Approach for Your Jenkins Deployment?

The right approach depends on the deployment, not a fixed rule from either case study. A low-risk internal tool can often run on scoped native credentials, while anything touching production data or compliance-regulated systems needs the fuller move to dynamic secrets and certificate governance.

The decision point is usually blast radius. A Jenkins job that only reads a low-value internal API can reasonably stay on well-scoped native credentials, following the same DevOps secrets management best practices either way. A job that deploys to production, touches customer data, or falls under SOC 2, HIPAA, or PCI DSS scope needs rotation, an audit trail, and short-lived credentials that a Script Console compromise can’t simply decrypt.

FAQs About Jenkins Secrets Management

Can Jenkins Credentials Be Managed as Code Instead of Through the UI?

Yes. Jenkins Configuration as Code (JCasC) lets teams define credentials in YAML instead of clicking through the UI, which fits GitOps-style infrastructure workflows. The underlying storage and decryption model, the same three-file chain and Script Console exposure described above, stays the same either way; JCasC changes how a credential gets defined, not how securely it’s stored.

Does a Running Jenkins Pipeline Need to Restart to Pick Up a Rotated Secret?

No. Both the native withCredentials step and the Akeyless plugin inject a secret at the moment a pipeline stage runs, not once at Jenkins startup, so the next pipeline run picks up whatever value is currently stored without any restart. A new value can take effect on the very next run, which is exactly why short-lived, dynamic credentials work at all.

Is There a Way to See Which Jenkins Jobs Have Access to a Given Credential?

Not easily. Jenkins’ native credential store doesn’t provide a built-in way to see which jobs reference a given Global-scoped credential; confirming that requires manually inspecting each job’s configuration or Jenkinsfile. It’s the same visibility limitation covered above, and it’s exactly what a centralized secrets manager restores by logging every access at the credential level, not the job level.

Does the withCredentials Step Fully Protect a Secret From Leaking?

It masks the secret in console output for straightforward references, but encoding tricks like piping a value through base64 can still reveal it, and a pipeline written to print characters individually can bypass the masking entirely.

What Compliance Frameworks Require More Than Jenkins’ Native Credential Store?

SOC 2, HIPAA, and PCI DSS all expect documented access controls, audit trails, and credential management practices that Jenkins’ native store doesn’t provide on its own, since it keeps no record of who accessed a secret or when. A SOC 2 and ISO 27001-certified secrets manager provides the missing audit trail natively.

Do I Need to Replace Jenkins’ Native Credentials Entirely to Improve Security?

Not necessarily. Many teams keep native credentials for low-risk, non-production jobs and move only production and compliance-scoped secrets to a dedicated secrets manager.

Does Akeyless’s Jenkins Plugin Work With Both Freestyle and Pipeline Jobs?

Yes. The Akeyless plugin supports Freestyle projects through the Environment configuration section and Pipeline jobs through the plugin’s configuration steps, per the official plugin listing on plugins.jenkins.io.

Never Miss an Update

 

The latest news and insights about Secrets Management,
Akeyless, and the community we serve.

 

Ready to get started?

Discover how Akeyless simplifies secrets management, reduces sprawl, minimizes risk, and saves time.

Get a Demo