Jenkins is one of the most widely deployed CI/CD platforms in the world — and one of the most targeted. Because Jenkins interacts with source repositories, build servers, deployment environments, and production secrets, a compromised Jenkins instance can mean a compromised entire software supply chain.
Why Jenkins Security Matters
Jenkins typically holds:
- Source code access credentials
- Deployment keys and cloud provider credentials
- Environment secrets and API tokens
- Access to production systems
A single misconfigured plugin or overly permissive access policy can expose all of this. The Jenkins security advisories page lists dozens of plugin vulnerabilities discovered each year.
Vulnerable Plugins Highlighted in 2022
The Jenkins security team issued advisories covering several widely-used plugins:
- Active Directory Plugin — transmitted credentials in plain text, exposing domain credentials to network sniffers
- Badge Plugin — XSS vulnerability allowing stored script injection in build badges
- Git Plugin — arbitrary file read vulnerability
- Pipeline: Shared Groovy Libraries — allowed sandbox bypass and arbitrary code execution
- Script Security Plugin — multiple sandbox escape vulnerabilities
Keep plugins updated and remove any that are unused or unmaintained.
13 Security Best Practices
1. Never Build on the Controller
Run builds on agents, not the Jenkins controller. The controller has access to all credentials and configuration — running untrusted build code there is a serious risk.
// Always specify an agent, never use `agent none` on the controller
pipeline {
agent { label 'build-agent' }
stages { ... }
}
2. Implement Access Control
Jenkins has two layers of access control: security realm (authentication) and authorization strategy (what authenticated users can do). Both must be configured.
3. Use Matrix-Based Authorization
The Project-based Matrix Authorization Strategy gives you fine-grained control:
- Admins: full access
- Developers: read/build their own jobs
- QA: read + test trigger
- Ops: deploy-specific jobs only
4. Sanitize Environment Variables
Build scripts frequently log environment variables. Ensure secrets are stored as Jenkins credentials and accessed via the credentials() binding — never passed as plain environment variables.
// WRONG: Secret visible in build logs
environment {
API_KEY = "supersecret123"
}
// CORRECT: Masked credential
environment {
API_KEY = credentials('my-api-key-credential-id')
}
5. Enable CSRF Protection
Jenkins has built-in CSRF protection via crumb tokens. Ensure it’s enabled in Manage Jenkins → Configure Global Security → CSRF Protection.
6. Use the Script Security Plugin
All Groovy scripts in pipelines run in a sandbox by default. Review and minimize the scripts that require sandbox escapes (approved scripts).
7. Restrict the Groovy Sandbox Escape List
Scripts approved to run outside the sandbox have full JVM access. Audit your approved scripts list regularly and remove approvals that are no longer needed.
8. Enable Audit Logging
Use the Audit Trail plugin to log all configuration changes, credential accesses, and build triggers. This is essential for incident investigation.
9. Rotate Credentials Regularly
Integrate with a secrets manager (HashiCorp Vault, AWS Secrets Manager) rather than storing long-lived credentials in Jenkins. Rotate them on a schedule.
10. Scan Dependencies in the Pipeline
Add dependency scanning as a required pipeline stage:
stage('Security Scan') {
steps {
sh 'mvn dependency-check:check'
// or npm audit, cargo audit, etc.
}
}
11. Pin Plugin Versions
Use the Plugin Installation Manager Tool to lock your plugin versions in a plugins.txt file. Uncontrolled automatic plugin updates can introduce regressions and vulnerabilities.
12. Network Isolation
Jenkins agents should not have direct access to production systems. Use deployment pipelines that communicate through controlled channels rather than giving agents direct network access.
13. Add SAST to Every Pipeline
Integrate static application security testing as a mandatory step before merge or deployment. A broken security scan should block the build.
stage('SAST') {
steps {
// Scan and fail the build if critical findings are detected
sh 'offensive360-scan --fail-on critical'
}
}
Incident Response for Compromised Jenkins
If you suspect a Jenkins compromise:
- Immediately revoke all stored credentials
- Rotate all service account passwords and API keys Jenkins had access to
- Review recent build logs for unauthorized commands
- Check for unauthorized job creation or configuration changes in the audit trail
- Rebuild the controller from a known-good state
Summary
Jenkins security is a layered problem: plugin vulnerabilities, access control misconfigurations, and insecure pipeline practices each contribute to the attack surface. Address all three layers, integrate SAST into every pipeline, and treat your CI/CD infrastructure as production infrastructure — because it effectively is.