Securing GitHub Actions Workflows
Security is critical in CI/CD pipelines. Learn to protect secrets and follow security best practices.
Using GitHub Secrets
Store sensitive data securely:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy with secrets
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: |
echo "Deploying with credentials..."
./deploy.sh
Environment-Specific Secrets
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- name: Deploy to staging
env:
API_URL: ${{ secrets.STAGING_API_URL }}
run: ./deploy.sh
deploy-production:
runs-on: ubuntu-latest
environment: production
steps:
- name: Deploy to production
env:
API_URL: ${{ secrets.PRODUCTION_API_URL }}
run: ./deploy.sh
Required Reviewers
Protect production deployments:
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- name: Deploy
run: ./deploy.sh
In repository settings → Environments → production:
- Add required reviewers
- Set deployment branches
- Configure environment secrets
Secret Scanning Prevention
steps:
- name: Safe secret usage
env:
SECRET: ${{ secrets.MY_SECRET }}
run: |
# Never echo secrets
# echo "$SECRET" ❌
# Use in commands safely
curl -H "Authorization: Bearer $SECRET" https://api.example.com ✅
Least Privilege Principle
permissions:
contents: read
pull-requests: write
issues: write
jobs:
comment:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({...})
Dependency Security
name: Dependency Check
on:
push:
branches: [main]
schedule:
- cron: '0 0 * * 0' # Weekly
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run npm audit
run: npm audit --audit-level=high
- name: Check for outdated packages
run: npm outdated
Code Scanning
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: javascript
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
Artifact Security
- name: Upload secure artifact
uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
if-no-files-found: error
Third-Party Actions Security
# Pin to specific version (recommended)
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.0.0
# Or use version tag
- uses: actions/checkout@v4
# Avoid using @main or @master
- uses: some-org/some-action@main # ❌ Not recommended
Security Checklist
✅ Use GitHub Secrets - Never hardcode credentials
✅ Environment protection - Require reviews for production
✅ Least privilege - Minimal permissions
✅ Pin action versions - Use commit SHA or version tags
✅ Audit dependencies - Regular security checks
✅ Code scanning - Enable CodeQL
✅ Rotate secrets - Regular secret rotation
✅ Monitor logs - Watch for suspicious activity
Common Vulnerabilities
❌ Logging secrets - Never echo or console.log secrets
❌ Broad permissions - Don’t use write-all
❌ Untrusted input - Sanitize user inputs
❌ Outdated actions - Keep actions updated
Key Takeaways
Security in GitHub Actions requires careful secrets management, minimal permissions, and regular audits. Always use GitHub Secrets, pin action versions, and implement code scanning for comprehensive protection.