Engineering

Jenkins Security Checklist: Hardening Your CI/CD Pipeline

Amjad Syed - Founder & CEO

Jenkins is a high-value target. It has access to your source code, deployment credentials, and production environments. A compromised Jenkins instance can lead to supply chain attacks, data breaches, and unauthorized deployments.

Yet many Jenkins installations run with default configurations that leave them vulnerable. This checklist covers the security controls that matter, organized by priority.

Critical: Authentication and Access Control

Enable Security

This seems obvious, but we still encounter Jenkins instances with security disabled.

  1. Navigate to Manage Jenkins > Security
  2. Enable Security Realm (authentication)
  3. Enable Authorization (access control)
  4. Save and verify you can still log in
// Check via Groovy console (disable after use)
println Jenkins.instance.isUseSecurity()
// Should return: true

Use External Authentication

Do not rely on Jenkins’ built-in user database for production. Integrate with your organization’s identity provider.

Recommended options:

Configuration example for LDAP:

# JCasC configuration
jenkins:
  securityRealm:
    ldap:
      configurations:
        - server: "ldap://ldap.example.com"
          rootDN: "dc=example,dc=com"
          userSearchBase: "ou=users"
          userSearch: "uid={0}"
          groupSearchBase: "ou=groups"

Implement Role-Based Access Control

The Role-based Authorization Strategy plugin provides granular access control.

Define roles based on job function:

RolePermissions
AdminFull system access
DeveloperBuild jobs, view logs, no system config
DeployerTrigger deployments, approve releases
ViewerRead-only access to build results
# JCasC configuration for role-based auth
jenkins:
  authorizationStrategy:
    roleBased:
      roles:
        global:
          - name: "admin"
            permissions:
              - "Overall/Administer"
            assignments:
              - "admin-group"
          - name: "developer"
            permissions:
              - "Job/Build"
              - "Job/Read"
              - "Job/Workspace"
            assignments:
              - "dev-group"

Enforce Strong Password Policies

If using Jenkins’ built-in database (not recommended for production):

  1. Install the Password Strength plugin
  2. Configure minimum password requirements
  3. Enable account lockout after failed attempts

Better: Use external authentication with your organization’s password policies.

Critical: Credentials Management

Use the Credentials Plugin Properly

Never store credentials in:

  • Jenkinsfiles
  • Environment variables in job config
  • Shared library code
  • Build parameters

Always use the Credentials plugin:

// Correct way to use credentials
pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                withCredentials([
                    usernamePassword(
                        credentialsId: 'deploy-creds',
                        usernameVariable: 'DEPLOY_USER',
                        passwordVariable: 'DEPLOY_PASS'
                    )
                ]) {
                    sh './deploy.sh'
                }
            }
        }
    }
}

Scope Credentials Appropriately

Credentials can be scoped to:

  • System - Available to Jenkins system operations
  • Global - Available to all jobs (avoid unless necessary)
  • Folder - Available only to jobs in that folder

Use folder-scoped credentials to limit blast radius:

Jenkins/
├── Production/           # Folder with prod credentials
│   ├── deploy-app-a/
│   └── deploy-app-b/
└── Development/          # Folder with dev credentials
    ├── build-app-a/
    └── build-app-b/

Rotate Credentials Regularly

Implement credential rotation:

  1. Track expiration dates - Document when credentials should rotate
  2. Automate where possible - Use tools like HashiCorp Vault for dynamic secrets
  3. Test rotation - Verify jobs work with new credentials before removing old ones

The HashiCorp Vault plugin enables dynamic credential retrieval:

pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                withVault([
                    vaultSecrets: [[
                        path: 'secret/data/deploy',
                        secretValues: [
                            [envVar: 'DB_PASSWORD', vaultKey: 'password']
                        ]
                    ]]
                ]) {
                    sh './deploy.sh'
                }
            }
        }
    }
}

Audit Credential Usage

Enable credential tracking:

  1. Install Credentials Binding plugin
  2. Review console output for credential bindings
  3. Monitor credential access in audit logs

High Priority: Plugin Security

Keep Plugins Updated

Outdated plugins are a common attack vector. Jenkins publishes security advisories regularly.

Establish an update process:

  1. Check weekly for security updates
  2. Test in staging before production updates
  3. Subscribe to the Jenkins security mailing list
# Check for plugin updates via CLI
java -jar jenkins-cli.jar -s http://jenkins:8080/ list-plugins | grep -i update

Remove Unused Plugins

Every plugin increases attack surface. Audit and remove plugins you do not use:

  1. Navigate to Manage Jenkins > Plugins > Installed
  2. Review each plugin’s purpose
  3. Uninstall unused plugins
  4. Restart Jenkins

Verify Plugin Sources

Only install plugins from:

Never install plugins from:

  • Random GitHub repositories
  • Untrusted third parties
  • Direct .hpi file uploads (unless internally developed and reviewed)

High Priority: Network Security

Enable HTTPS

Never run Jenkins over plain HTTP in production.

Using a reverse proxy (recommended):

# Nginx configuration
server {
    listen 443 ssl;
    server_name jenkins.example.com;

    ssl_certificate /etc/ssl/certs/jenkins.crt;
    ssl_certificate_key /etc/ssl/private/jenkins.key;
    ssl_protocols TLSv1.2 TLSv1.3;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Configure Jenkins to recognize the proxy:

# JCasC configuration
unclassified:
  location:
    url: "https://jenkins.example.com/"

Restrict Network Access

Jenkins should not be publicly accessible unless absolutely necessary.

Firewall rules:

  • Allow HTTPS (443) from authorized networks only
  • Allow agent connections (50000) from agent subnets only
  • Block all other inbound traffic

For Kubernetes deployments:

# NetworkPolicy to restrict Jenkins access
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: jenkins-network-policy
spec:
  podSelector:
    matchLabels:
      app: jenkins
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: authorized-namespace
      ports:
        - port: 8080

Secure Agent Communication

Configure agent-to-controller security:

  1. Navigate to Manage Jenkins > Security
  2. Under Agents, select Fixed or Random for TCP port
  3. Enable Agent → Controller Access Control
# JCasC configuration
jenkins:
  slaveAgentPort: 50000
  agentProtocols:
    - "JNLP4-connect"

For Kubernetes-based agents, use in-cluster communication:

pipeline {
    agent {
        kubernetes {
            yaml '''
                apiVersion: v1
                kind: Pod
                spec:
                  containers:
                  - name: jnlp
                    image: jenkins/inbound-agent:latest
            '''
        }
    }
}

Medium Priority: Build Security

Sandbox Pipeline Scripts

Enable the Groovy sandbox for pipeline scripts:

  1. Navigate to Manage Jenkins > In-process Script Approval
  2. Review and approve only necessary script signatures
  3. Reject broad approvals like method groovy.lang.Script run

The sandbox prevents pipelines from accessing Jenkins internals or executing arbitrary code.

Restrict Script Console Access

The Groovy Script Console can execute any code on the Jenkins controller. Restrict access:

  1. Only administrators should access the script console
  2. Audit script console usage
  3. Consider disabling it entirely in production
# Disable script console via JCasC
jenkins:
  disabledAdministrativeMonitors:
    - "hudson.diagnosis.ReverseProxySetupMonitor"

Validate Pipeline Sources

For multibranch pipelines, control which branches can run pipelines:

// Only allow Jenkinsfiles from main and release branches
properties([
    [$class: 'BuildDiscarderProperty',
     strategy: [$class: 'LogRotator', numToKeepStr: '10']],
    [$class: 'JobPropertyImpl',
     branch: [
        [$class: 'BranchSource',
         source: [$class: 'GitSCMSource',
                  includes: 'main release/*']]
     ]]
])

Scan for Secrets in Build Output

Prevent accidental credential leakage:

  1. Install the Mask Passwords plugin
  2. Configure it to mask sensitive patterns
  3. Review build logs regularly for exposed secrets
# JCasC configuration
unclassified:
  globalMaskPasswordsConfig:
    maskPasswordsParamDefNames:
      - "password"
      - "secret"
      - "apikey"
      - "token"

Medium Priority: Audit and Monitoring

Enable Audit Logging

Track who does what:

  1. Install the Audit Trail plugin
  2. Configure logging to a file or syslog
  3. Integrate with your SIEM
# JCasC configuration
unclassified:
  audit-trail:
    logBuildCause: true
    pattern: ".*/(?:configSubmit|doDelete|postBuildResult|build|toggleLogKeep)"
    loggers:
      - log:
          name: "/var/log/jenkins/audit.log"

Monitor for Anomalies

Set up alerts for suspicious activity:

  • Failed login attempts
  • Credential access outside normal hours
  • Configuration changes
  • New admin users
  • Plugin installations

We integrate Jenkins audit logs with Prometheus and Grafana for real-time security monitoring.

Regular Security Scans

Run periodic security assessments:

  1. Dependency scanning - Check for vulnerable dependencies in builds
  2. Configuration review - Verify security settings quarterly
  3. Penetration testing - Annual security assessment

Configuration as Code

Use JCasC for Reproducibility

The Configuration as Code plugin enables version-controlled security configuration:

# Complete security configuration
jenkins:
  securityRealm:
    ldap:
      configurations:
        - server: "ldap://ldap.example.com"
          rootDN: "dc=example,dc=com"

  authorizationStrategy:
    roleBased:
      roles:
        global:
          - name: "admin"
            permissions:
              - "Overall/Administer"
            assignments:
              - "jenkins-admins"

  remotingSecurity:
    enabled: true

  slaveAgentPort: 50000
  agentProtocols:
    - "JNLP4-connect"

unclassified:
  location:
    url: "https://jenkins.example.com/"

Store this in version control (without sensitive values). Use Kubernetes secrets or environment variables for sensitive configuration.

Security Checklist Summary

Use this checklist for your Jenkins security review:

Critical

  • Security is enabled (authentication + authorization)
  • External authentication configured (LDAP, SAML, OAuth)
  • Role-based access control implemented
  • Credentials stored in Credentials plugin, not in code
  • Credentials scoped appropriately (folder-level when possible)

High Priority

  • All plugins updated to latest versions
  • Unused plugins removed
  • HTTPS enabled
  • Network access restricted to authorized users
  • Agent-to-controller security enabled

Medium Priority

  • Pipeline sandbox enabled
  • Script console access restricted
  • Audit logging configured
  • Build output scanned for leaked secrets
  • Configuration as Code implemented

Ongoing

  • Weekly plugin update review
  • Quarterly configuration audit
  • Annual penetration test
  • Credential rotation schedule maintained

Next Steps

Security is not a one-time task. Schedule regular reviews, subscribe to Jenkins security advisories, and train your team on secure pipeline practices.

For teams implementing new Jenkins installations, our Jenkins pipeline best practices guide covers secure-by-default patterns. If you are evaluating alternatives, see our comparison of Jenkins vs GitHub Actions.


Need Help Securing Jenkins?

We help organizations harden their Jenkins installations and implement secure CI/CD practices. Our Jenkins consulting services include security assessments, hardening implementations, and ongoing support.

Book a free 30-minute consultation to discuss your Jenkins security posture.

Chat with real humans
Chat on WhatsApp