From grimoire
Hardens CI/CD pipelines: restrict permissions, pin actions to SHAs, sign artifacts with Sigstore/cosign, inject secrets from vaults. For GitHub Actions, GitLab CI, Jenkins.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:design-cicd-pipeline-securityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Secure CI/CD pipelines by restricting pipeline permissions to least privilege, injecting secrets from vaults (not env vars), signing artifacts with Sigstore/cosign, and pinning actions to commit SHAs — preventing secret exfiltration and supply chain attacks.
Secure CI/CD pipelines by restricting pipeline permissions to least privilege, injecting secrets from vaults (not env vars), signing artifacts with Sigstore/cosign, and pinning actions to commit SHAs — preventing secret exfiltration and supply chain attacks.
Adopted by: OWASP CI/CD Security Cheat Sheet (2023) and CNCF Software Supply Chain Best Practices define the standard. The SLSA Framework (slsa.dev, backed by Google, Microsoft, NIST) provides a supply chain integrity maturity model adopted by GitHub, GitLab, and npm. NIST SP 800-218 (SSDF) mandates supply chain controls for US federal software. GitHub, Google, and Shopify all use artifact signing and pinned action versions in production pipelines. Impact: The 2021 Codecov breach compromised CI environment variables and exfiltrated credentials from thousands of pipelines. The 2020 SolarWinds attack injected malicious code at the build stage — directly what SLSA framework prevents. GitHub's own research (2022) found 95% of GitHub Actions workflows use at least one unpinned action, enabling tag mutation attacks. CircleCI's 2023 breach was caused by compromised CI credentials exposed in pipeline logs. Why best: Pipeline security vs. application security: application security controls (SAST, SCA) catch code vulnerabilities, but pipeline security prevents the pipeline itself from becoming an attack vector. An attacker with pipeline access can inject arbitrary code, exfiltrate all secrets, and publish malicious artifacts — bypassing all code review and security scanning.
Sources: OWASP CI/CD Security Cheat Sheet; CNCF Software Supply Chain Best Practices Guide; SLSA framework specification; NIST SP 800-218; GitHub Security Lab research (2022)
Restrict GitHub Actions pipeline permissions to minimum required:
# At top of workflow — restrict all permissions
permissions:
contents: read # only what's needed
# Or per-job
jobs:
build:
permissions:
contents: read
packages: write # only for publish job
# Never use: permissions: write-all
# Default GitHub token has read-all — explicitly restrict
Pin actions to commit SHAs, not tags — tags are mutable:
# BAD — tag can be changed to point at malicious code
- uses: actions/checkout@v4
- uses: actions/setup-node@main
# GOOD — SHA is immutable
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
Use Dependabot to auto-update pinned SHAs:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
Never hardcode secrets — use GitHub Secrets or a vault:
# BAD — secret visible in logs if run echoes it
env:
DATABASE_URL: postgresql://user:password@host/db
# GOOD — reference from GitHub Secrets
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
# BETTER — fetch from HashiCorp Vault or AWS Secrets Manager at runtime
- name: Import secrets from Vault
uses: hashicorp/vault-action@d1720f055e0635fd932a1d2a48f87a666a57906c # v3.0.0
with:
url: https://vault.company.com
method: jwt
role: github-actions-role
secrets: |
secret/data/production/db password | DATABASE_PASSWORD
Sign container images and binaries with Sigstore/cosign:
- name: Sign image with cosign (keyless — uses OIDC)
run: |
cosign sign --yes \
registry.company.com/myapp:${{ github.sha }}
# Verify signature before deploying
cosign verify \
--certificate-identity "https://github.com/company/myapp/.github/workflows/release.yml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
registry.company.com/myapp:abc123
Generate and verify SBOM (Software Bill of Materials):
- name: Generate SBOM
uses: anchore/sbom-action@e8d2a6937ecead383dfe75190d104edd1f9c5666 # v0.15.0
with:
image: registry.company.com/myapp:${{ github.sha }}
format: spdx-json
output-file: sbom.spdx.json
- name: Attest SBOM to image
run: |
cosign attest --yes \
--predicate sbom.spdx.json \
--type spdxjson \
registry.company.com/myapp:${{ github.sha }}
Isolate pipeline environments — separate jobs for build vs. deploy:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# No production credentials here
deploy:
needs: build
runs-on: ubuntu-latest
environment: production # requires manual approval
permissions:
id-token: write # for OIDC auth to cloud
steps:
- name: Configure AWS credentials via OIDC (no long-lived keys)
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: arn:aws:iam::123456789:role/github-actions-deploy
aws-region: us-east-1
echo $SECRET is visible in logs even if the secret is masked by GitHub.pull_request_target with checkout of PR head — pull_request_target runs with write permissions; checking out untrusted PR code gives attackers write access.actions/cache may persist files containing secrets across runs; exclude sensitive directories.npx claudepluginhub jeffreytse/grimoire --plugin grimoireHardens GitHub Actions workflows against supply chain attacks, credential theft, and script injection. Covers SHA pinning, token permissions, and injection prevention.
Hardens GitHub Actions workflows against supply chain attacks, credential theft, and script injection. Covers SHA pinning, token permissions, and injection prevention.
Hardens GitHub Actions workflows against supply chain attacks, credential theft, and privilege escalation by pinning actions to SHA digests, minimizing GITHUB_TOKEN permissions, preventing script injection, and adding reviewer gates.