--- name: github-actions-advanced description: > Design, debug, and harden GitHub Actions CI/CD workflows, including reusable workflows, matrix builds, self-hosted runners, OIDC authentication, caching, environments, secrets, and release automation. category: devops risk: critical source: community date_added: "2026-05-30" --- # GitHub Actions Advanced Skill Expert guidance for designing, writing, debugging, and securing **production-grade** GitHub Actions workflows. --- ## Detailed Guide Read [the detailed guide](references/detailed-guide.md) before executing this skill. It retains the complete procedure and reference material. Treat its safety, prerequisites, and validation requirements as mandatory. For focused work, load the relevant sections; for end-to-end work, read the guide completely. ## When to Use This Skill - User mentions GitHub Actions, `.github/workflows`, CI/CD pipelines, runners, jobs, steps, or actions - User wants to automate builds, tests, deployments, or releases via GitHub - User asks about matrix builds, reusable workflows, composite actions, or self-hosted runners - User needs help with OIDC authentication, caching strategies, or secrets management - User says "my GitHub pipeline is failing" or "set up CI for my repo" - User asks about workflow security, hardening, or environment protection rules ## When NOT to Use This Skill - The user is working with GitLab CI/CD → recommend `gitlab-ci-patterns` - The user is working with CircleCI, Jenkins, or other CI platforms - The task is purely about Docker image building without GitHub context → recommend `docker-expert` - The task is about Kubernetes deployment configuration → recommend `kubernetes-architect` --- ## Security Hardening ### 1. Always Declare Permissions (Least Privilege) ```yaml # Workflow-level default — restrict everything permissions: contents: read jobs: publish: # Job-level override — only expand what's needed permissions: contents: write # Only for release/publish jobs packages: write # Only for container push jobs pull-requests: write # Only for PR comment jobs id-token: write # Only for OIDC auth jobs ``` ### 2. Pin Third-Party Actions to Full Commit SHA ```yaml # ❌ UNSAFE — tag can be mutated or hijacked - uses: actions/checkout@v4 # Full SHA prevents tag movement; verify its origin and content (not a safety certification) - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Tool to automate SHA pinning: # npx pin-github-action .github/workflows/*.yml # or: pip install ratchet && ratchet pin .github/workflows/ ``` ### 3. Prevent Script Injection ```yaml # ❌ UNSAFE — attacker controls PR title, which gets expanded in shell - run: echo "${{ github.event.pull_request.title }}" # ✅ SAFE — pass through environment variable (shell doesn't evaluate it) - env: PR_TITLE: ${{ github.event.pull_request.title }} run: echo "$PR_TITLE" # ✅ SAFE — expressions in if: conditions are evaluated by Actions, not shell - if: github.event.pull_request.draft == false run: echo "Not a draft" ``` Never place `${{ ... }}` directly inside `run:` when the value can come from PR metadata, workflow inputs, repository files, matrix JSON, or earlier job outputs. Put it in `env:` first, validate allowlisted values where possible, and reference the shell variable with quotes. ### 4. Restrict `pull_request_target` Usage ```yaml # A label/association gate alone does NOT prevent untrusted execution. # Use this event only for trusted base-code metadata tasks with narrow permissions. on: pull_request_target: types: [labeled] jobs: validate: # Double-guard: check label name AND author_association if: | github.event.label.name == 'safe-to-test' && (github.event.pull_request.author_association == 'COLLABORATOR' || github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'OWNER') ``` Privileged jobs must not execute PR-controlled code or artifacts regardless of label. Check actor authorization and exact reviewed head for any separately approved action; a push after labeling changes the code. Restrict OIDC audience/subject to the exact repository and branch/environment, with minimal cloud roles. Never promote untrusted caches/artifacts into deployment code. ### 5. Harden with StepSecurity ```yaml # Optional third-party control: review version, permissions, supported runner and telemetry handling before adoption. - uses: step-security/harden-runner@4d991eb9995541a0b71d1b66f1f98a5f1bef422c # v2.11.0 with: egress-policy: audit # Start with 'audit', move to 'block' after confirming allowlist allowed-endpoints: > api.github.com:443 registry.npmjs.org:443 objects.githubusercontent.com:443 ``` --- ## Limitations - Use this skill only when the task clearly matches the scope described above. - Do not treat the output as a substitute for environment-specific validation, testing, or expert review. - Always test reusable workflows in a feature branch before merging to main. - Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.