Skip to content

CI/CD pipelines are critical infrastructure that can become attack vectors if not properly secured. This guide covers essential security practices for your DevOps workflows.

Pipeline Security Threats

Common Attacks

  • Dependency poisoning: Malicious packages
  • Code injection: Malicious commits
  • Secrets exposure: Leaked credentials
  • Supply chain attacks: Compromised tools
  • Privilege escalation: Excessive permissions

Securing Source Code

Branch Protection

1
2
3
4
5
6
7
# GitHub branch protection rules
main:
  required_reviews: 2
  require_code_owner_reviews: true
  dismiss_stale_reviews: true
  require_status_checks: true
  require_signed_commits: true

Commit Signing

1
2
3
4
5
6
# Configure GPG signing
git config --global user.signingkey YOUR_KEY_ID
git config --global commit.gpgsign true

# Sign commits
git commit -S -m "Signed commit"

Secrets Management

Never Hardcode Secrets

1
2
3
4
5
# ❌ Bad - secrets in code
DATABASE_URL: "postgresql://user:password@localhost/db"

# ✅ Good - use secret managers
DATABASE_URL: ${{ secrets.DATABASE_URL }}

GitHub Actions Secrets

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
name: Deploy
on: push

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Deploy
        env:
          API_KEY: ${{ secrets.API_KEY }}
        run: ./deploy.sh

HashiCorp Vault Integration

1
2
3
4
5
6
7
8
- name: Get secrets from Vault
  uses: hashicorp/vault-action@v2
  with:
    url: https://vault.example.com
    token: ${{ secrets.VAULT_TOKEN }}
    secrets: |
      secret/data/production db_password ;
      secret/data/production api_key      

Dependency Security

Dependency Scanning

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# GitHub Actions - Dependency Review
name: Dependency Review
on: [pull_request]

jobs:
  dependency-review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/dependency-review-action@v3

npm Audit

1
2
3
4
5
6
7
8
# Check for vulnerabilities
npm audit

# Fix automatically where possible
npm audit fix

# Force fix (may have breaking changes)
npm audit fix --force

Renovate Bot

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "extends": ["config:base"],
  "vulnerabilityAlerts": {
    "enabled": true
  },
  "automerge": true,
  "major": {
    "automerge": false
  }
}

Container Security

Secure Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Use specific versions, not 'latest'
FROM node:18.17-alpine

# Run as non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs

# Copy only necessary files
COPY --chown=nodejs:nodejs package*.json ./
RUN npm ci --only=production

COPY --chown=nodejs:nodejs . .

# Use read-only filesystem where possible
CMD ["node", "server.js"]

Image Scanning

1
2
3
4
5
6
7
- name: Scan image
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: myapp:${{ github.sha }}
    format: 'sarif'
    output: 'trivy-results.sarif'
    severity: 'CRITICAL,HIGH'

SAST (Static Application Security Testing)

CodeQL

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
name: CodeQL
on:
  push:
    branches: [main]
  pull_request:

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: github/codeql-action/init@v2
        with:
          languages: javascript, python
      - uses: github/codeql-action/autobuild@v2
      - uses: github/codeql-action/analyze@v2

SonarQube

1
2
3
4
5
- name: SonarQube Scan
  uses: sonarsource/sonarqube-scan-action@master
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
    SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

Access Control

Least Privilege

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# GitHub Actions - minimal permissions
permissions:
  contents: read
  pull-requests: write

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm test

OIDC Authentication

1
2
3
4
5
- name: Configure AWS Credentials
  uses: aws-actions/configure-aws-credentials@v2
  with:
    role-to-assume: arn:aws:iam::123456789012:role/GitHubActions
    aws-region: us-east-1

Pipeline as Code Security

Validate Pipeline Configs

1
2
3
4
5
6
7
8
9
# Pre-commit hook for pipeline validation
repos:
  - repo: local
    hooks:
      - id: validate-github-workflow
        name: Validate GitHub Workflows
        entry: actionlint
        language: system
        files: ^\.github/workflows/.*\.yml$

Audit Pipeline Changes

1
2
3
4
5
- name: Pipeline Change Notification
  if: contains(github.event.head_commit.modified, '.github/workflows')
  run: |
    echo "Pipeline modified - security review required"
    # Send notification to security team    

Monitoring and Logging

Audit Logs

1
2
3
4
5
6
- name: Log deployment
  run: |
    echo "Deployment by ${{ github.actor }}"
    echo "Commit: ${{ github.sha }}"
    echo "Timestamp: $(date)"
    # Send to centralized logging    

Alerting

1
2
3
4
5
6
7
- name: Notify on failure
  if: failure()
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    text: 'Pipeline failed - investigate immediately'
    webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Compliance

Policy Enforcement

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Open Policy Agent
package pipeline

deny[msg] {
    input.image.tag == "latest"
    msg = "Using 'latest' tag is not allowed"
}

deny[msg] {
    not input.image.signed
    msg = "Only signed images are allowed"
}

SBOM Generation

1
2
3
4
5
6
- name: Generate SBOM
  uses: anchore/sbom-action@v0
  with:
    image: myapp:${{ github.sha }}
    format: spdx-json
    output-file: sbom.json

Best Practices

  1. Minimal permissions: Grant only necessary access
  2. Secrets rotation: Regularly rotate credentials
  3. Immutable builds: Never modify published artifacts
  4. Audit everything: Comprehensive logging
  5. Automated scanning: Integrate security tools
  6. Signed artifacts: Verify authenticity
  7. Isolated environments: Separate dev/staging/prod
  8. Regular updates: Keep tools and dependencies current

Incident Response

Pipeline Compromise Plan

  1. Immediately revoke all secrets
  2. Audit recent pipeline runs
  3. Review code changes
  4. Scan for malicious artifacts
  5. Notify affected parties
  6. Post-mortem analysis

Conclusion

CI/CD pipeline security is crucial for protecting your software supply chain. Implement these practices to build secure, trustworthy deployment processes.