DEV Community

Atlas Whoff
Atlas Whoff

Posted on

GitHub Actions Secrets: Managing Credentials Safely in CI/CD

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)