GitHub Actions Secrets: Managing Credentials Safely in CI/CD
Leaked credentials in CI/CD pipelines are one of the most common causes of security incidents. Here's the right way to manage secrets in GitHub Actions.
Never Do This
# BAD — credentials visible in logs and git history
- name: Deploy
run: |
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE \
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \
./deploy.sh
GitHub Secrets: The Basics
Store secrets in Settings → Secrets and variables → Actions:
# Good — secrets injected as environment variables
- name: Deploy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: ./deploy.sh
GitHub automatically masks secret values in logs. If a secret appears in output, it shows as ***.
Environment-Scoped Secrets
Use deployment environments to scope secrets to specific contexts:
jobs:
deploy-staging:
environment: staging # Uses staging-scoped secrets
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to staging
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }} # staging DB
run: ./deploy.sh staging
deploy-production:
environment: production # Different secrets, requires approval
needs: deploy-staging
runs-on: ubuntu-latest
steps:
- name: Deploy to production
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }} # prod DB
run: ./deploy.sh production
OIDC: No Long-Lived Credentials
The best practice: don't store cloud credentials at all. Use OIDC to get short-lived tokens:
permissions:
id-token: write # Required for OIDC
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/GitHubActions
aws-region: us-east-1
# No access keys needed — GitHub gets a temporary token
This eliminates the risk of long-lived credential leakage entirely.
Secret Scanning
Enable GitHub's secret scanning (free for public repos, included in GitHub Advanced Security):
- Settings → Security → Secret scanning
- Scans every commit for known credential patterns
- Alerts you if a secret is detected and can auto-revoke some credentials
Rotating Secrets
# Rotate a secret via GitHub CLI
gh secret set AWS_ACCESS_KEY_ID --body 'NEWKEYVALUE' --repo owner/repo
gh secret set AWS_SECRET_ACCESS_KEY --body 'NEWSECRETVALUE' --repo owner/repo
MCP Security in Automated Pipelines
When CI/CD pipelines invoke MCP tools — for deployment, testing, or automation — credential handling becomes critical. The MCP Security Scanner audits MCP server configurations for exposed credentials, missing authentication, and injection vectors before they reach production.
Top comments (0)