Verified by Garnet Grid

How to Secure Your CI/CD Pipeline: Vulnerability Scanning and Access Control

Harden your CI/CD pipeline against supply chain attacks. Covers runner security, artifact signing, RBAC, pipeline secrets management, and audit logging.

Your CI/CD pipeline has more access than any developer. It touches your source code, builds your binaries, handles your secrets, and deploys to production. If an attacker compromises your pipeline, they own everything.


Step 1: Secure Pipeline Secrets

1.1 Never Store Secrets in Code

# ❌ NEVER do this
env:
  DATABASE_URL: "postgres://admin:P@ssw0rd@prod-db:5432/main"

# ✅ Use GitHub Secrets or a vault
env:
  DATABASE_URL: ${{ secrets.DATABASE_URL }}

1.2 Use Environment-Scoped Secrets

# GitHub Actions — environment protection
jobs:
  deploy-prod:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://myapp.com
    steps:
      - name: Deploy
        env:
          # These secrets are only accessible when deploying to 'production'
          AWS_ACCESS_KEY: ${{ secrets.PROD_AWS_ACCESS_KEY }}
          AWS_SECRET_KEY: ${{ secrets.PROD_AWS_SECRET_KEY }}
        run: ./deploy.sh

1.3 Rotate Secrets Automatically

# AWS Secrets Manager — automatic rotation
aws secretsmanager rotate-secret \
  --secret-id prod/database \
  --rotation-lambda-arn arn:aws:lambda:us-east-1:123456:function:rotate-db-secret \
  --rotation-rules '{"AutomaticallyAfterDays": 30}'

Step 2: Lock Down Pipeline Permissions

2.1 GitHub Actions OIDC (No Long-lived Credentials)

permissions:
  id-token: write
  contents: read

steps:
  - name: Configure AWS Credentials (OIDC)
    uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
      aws-region: us-east-1
      # No access keys needed! Uses OIDC federation

2.2 Least Privilege for Pipeline Service Accounts

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:PutImage"
      ],
      "Resource": "arn:aws:ecr:us-east-1:123456:repository/myapp"
    },
    {
      "Effect": "Allow",
      "Action": ["ecs:UpdateService"],
      "Resource": "arn:aws:ecs:us-east-1:123456:service/myapp-prod/*"
    }
  ]
}

Step 3: Verify Build Integrity

3.1 Sign Your Artifacts

# Cosign — sign container images
cosign sign --key cosign.key myregistry.com/myapp:v1.2.3

# Verify before deployment
cosign verify --key cosign.pub myregistry.com/myapp:v1.2.3

3.2 Generate SBOM (Software Bill of Materials)

# Syft — generate SBOM
syft myregistry.com/myapp:v1.2.3 -o spdx-json > sbom.json

# Grype — scan SBOM for vulnerabilities
grype sbom:sbom.json --fail-on high

Step 4: Protect Branch and Deployment Rules

# Branch protection via GitHub API
gh api repos/{owner}/{repo}/branches/main/protection \
  --method PUT \
  --field required_status_checks='{"strict":true,"contexts":["security-scan","tests"]}' \
  --field enforce_admins=true \
  --field required_pull_request_reviews='{"required_approving_review_count":2,"dismiss_stale_reviews":true}' \
  --field restrictions=null

Required Checks Before Merge

CheckPurposeBlocks Merge?
Unit TestsCode correctness✅ Yes
SAST ScanCode vulnerabilities✅ Yes
Dependency AuditKnown CVEs✅ Yes (high/critical)
Container ScanImage vulnerabilities✅ Yes
Code ReviewHuman approval (2+)✅ Yes
License CheckOSS compliance⚠️ Warning only

Step 5: Monitor Pipeline Activity

  audit-logging:
    runs-on: ubuntu-latest
    steps:
      - name: Log Deployment
        run: |
          curl -X POST "${{ secrets.AUDIT_WEBHOOK }}" \
            -H "Content-Type: application/json" \
            -d '{
              "event": "deployment",
              "environment": "production",
              "commit": "${{ github.sha }}",
              "actor": "${{ github.actor }}",
              "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
              "workflow": "${{ github.workflow }}",
              "run_id": "${{ github.run_id }}"
            }'

Pipeline Security Checklist

  • No secrets in source code (use vault/environment secrets)
  • Environment-scoped secrets with approval gates
  • OIDC federation (no long-lived credentials)
  • Least-privilege service account permissions
  • Container image signing (Cosign)
  • SBOM generation and scanning
  • Branch protection with required checks
  • 2+ reviewer requirement for production deployments
  • Audit logging for all pipeline activities
  • Self-hosted runner hardening (if applicable)

:::note[Source] This guide is derived from operational intelligence at Garnet Grid Consulting. For DevOps maturity assessments, visit garnetgrid.com. :::