CI/CD Secrets Management: Securing GitHub Actions & GitLab CI
How to securely manage secrets in GitHub Actions, GitLab CI, and Jenkins. Prevent credential exposure in CI/CD pipelines.
CI/CD Secrets Management: Securing GitHub Actions & GitLab CI
To secure secrets in CI/CD pipelines, use built-in secret stores (GitHub Secrets, GitLab CI Variables), never echo secrets in logs, rotate credentials every 30 days, and consider integrating a dedicated secrets manager like XtraSecurity for enterprise-grade control. Here is how to do it for GitHub Actions, GitLab CI, and Jenkins.
Yet many teams handle secrets carelessly in GitHub Actions, GitLab CI, and Jenkins.
The CI/CD Secrets Problem
When you push code, your CI/CD pipeline springs into action:
- Clone repository
- Install dependencies
- Run tests
- Build application
- Deploy to production
At each step, secrets are needed. And at each step, they're exposed to logs, artifacts, and environment variables.
GitHub Actions Secrets: The Right Way
Creating Secrets in GitHub
- Go to Settings → Secrets and variables → Actions
- Click "New repository secret"
- Add your secret (API_KEY, DATABASE_PASSWORD, etc.)
Accessing Secrets in Workflows
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to production
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_KEY: ${{ secrets.API_KEY }}
run: npm run deploy
Never Log Secrets
✅ Good:
- name: Connect to database
env:
PASSWORD: ${{ secrets.DB_PASSWORD }}
run: npm run migrate # Password not logged
❌ Bad:
- name: Test
run: echo "Password is: ${{ secrets.DB_PASSWORD }}" # 🚨 EXPOSED
GitHub Actions Best Practices
- Use organization secrets for shared secrets
- Rotate secrets every 30 days
- Audit secret access logs
- Mask secret values in logs automatically (GitHub does this)
- Limit branch access to production secrets
GitLab CI Secrets
GitLab calls them "CI/CD Variables":
stages:
- deploy
deploy:
stage: deploy
script:
- export DATABASE_URL=$DB_URL
- npm run deploy
only:
- main
Jenkins Secrets
In Jenkins, use the Credentials Plugin:
pipeline {
agent any
environment {
API_KEY = credentials('api-key-prod')
}
stages {
stage('Deploy') {
steps {
sh '''
export API_KEY=${API_KEY}
npm run deploy
'''
}
}
}
}
Advanced: Integration with XtraSecurity
For enterprise CI/CD, integrate XtraSecurity:
name: Deploy with XtraSecurity
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Fetch secrets
run: |
npm install @xtrasecurity/sdk
node fetch-secrets.js
- name: Deploy
run: npm run deploy
Common CI/CD Secret Mistakes
❌ Storing secrets in code ❌ Committing .env files ❌ Using weak credentials ❌ No secret rotation ❌ Storing secrets in artifacts ❌ No audit logs
Conclusion
CI/CD pipelines should never expose secrets in logs, artifacts, or environment variables.
About the Author
OM Salunke — Full-stack developer and founder of XtraSecurity. Building secure infrastructure tools for modern engineering teams.