Github Actions Hardening
GitHubOfficialFirst committed by AmirhosseinHonardoustDistributed by GitHub
- Skill
- Review and audit
- Security
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
GitHub Actions Hardening is a security-focused reviewer designed to audit .github/workflows/*.yml files. Unlike general code linters, this skill identifies risks specific to the GitHub Actions threat model, such as untrusted input injection via ${{ }} interpolation, privilege escalation in workflow triggers, and supply-chain risks from mutable action references. It provides a structured audit process to ensure workflows follow the principle of least privilege and are resilient against common CI-based attacks.
What it does
- Identifies script injection vulnerabilities where ${{ }} expressions are interpolated directly into shell commands.
- Audits workflow triggers for privilege escalation risks, specifically targeting pull_request_target and workflow_run.
- Validates GITHUB_TOKEN permissions to ensure they follow the principle of least privilege.
- Checks for secure supply-chain practices, including mandatory SHA-pinning for third-party actions.
- Detects improper secret handling and potential exposure in logs or untrusted job contexts.
- Provides a structured report with severity ratings and concrete before/after remediation examples.
When to use it
- When auditing existing GitHub Actions workflows for security vulnerabilities.
- When authoring new CI/CD pipelines to ensure they are secure by default.
- When a workflow uses sensitive triggers like pull_request_target or workflow_run.
- When you need to harden GITHUB_TOKEN permissions or implement OIDC for cloud authentication.
- When you are concerned about supply-chain risks from third-party actions.
Advantages
- Focuses on CI-specific threat models that standard linters often ignore.
- Provides actionable, concrete remediation steps rather than just flagging issues.
- Helps prevent common RCE and token-theft scenarios in CI environments.
- Encourages secure-by-default practices like SHA-pinning and least-privilege permissions.
Usage examples
- “Is my workflow safe? [paste workflow YAML]”
- The agent will analyze the triggers, permissions, and run steps, providing a severity-ranked report with specific fixes for any identified injection or privilege risks.
- “Review my CI for security issues and suggest improvements.”
- The agent will perform a full audit of the provided workflow, flagging broad permissions, mutable action references, and unsafe input handling.
- “Why is pull_request_target dangerous here?”
- The agent will explain the trust boundary violation, detailing how the trigger runs with privileged access and how to split the workflow into a safer two-part pattern.
- “How can I lock down my GITHUB_TOKEN permissions?”
- The agent will provide a template for a restrictive permissions: {} block and guide you on how to grant only the necessary scopes per job.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/github/github-actions-hardening/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip github-actions-hardening.zip -d .agents/skills
Documentation by AmirhosseinHonardoust
GitHub Actions Hardening
A focused security reviewer for GitHub Actions workflows. It reasons about the Actions-specific
threat model — where trust boundaries live in trigger types, token scopes, and string
interpolation — rather than the application-code vulnerabilities a general security scanner looks
for. Most workflow risks are invisible to language linters because the dangerous code is the YAML
itself and the way GitHub expands ${{ }} expressions into a shell before your script runs.
When to Use This Skill
Use this skill when the request involves:
Reviewing, auditing, or hardening any file under
.github/workflows/Authoring a new workflow and wanting it secure by default
A workflow that uses
pull_request_target,workflow_run, orissue_commenttriggersQuestions about
GITHUB_TOKENpermissions or thepermissions:keyPinning actions to commit SHAs vs tags vs branches
Handling untrusted input (issue titles, PR bodies, branch names, commit messages) in
run:stepsOIDC / cloud authentication from Actions, or secret handling in CI
Self-hosted runners on public repositories
Any request like "is this workflow safe?", "secure my CI", or "review this GitHub Action"
The Core Insight
In a workflow, ${{ <expr> }} is expanded by the runner into the script before the shell
executes it. So a step like:
- run: echo "Title: ${{ github.event.issue.title }}"is not passing a variable — it is pasting attacker-controlled text directly into your shell
command. An issue titled "; <attacker-command> # is concatenated into the script and executed.
This single mechanism is the most common real-world Actions vulnerability, and models routinely
generate it. Treat every
${{ }} that contains data an outside contributor can influence as a code-injection sink.
Execution Workflow
Follow these steps in order for every workflow reviewed.
Step 1 — Map the Triggers and Trust Level
Read every on: trigger and classify the workflow's privilege:
push,pull_request(from same repo) → runs with the contributor's own trustpull_requestfrom a fork → runs with a read-only token, no secrets (safe by design)pull_request_target,workflow_run,issue_comment,issues→ run in the context of the base repository with a read/write token and full access to secrets, but can be triggered by outside contributors. These are the dangerous triggers.
Read references/triggers-and-privilege.md for the full trust matrix.
Step 2 — Hunt for Script Injection
For every run: block, every script: in actions/github-script, and every input to a custom
action, list the ${{ }} expressions and check whether any resolve to attacker-controllable data.
High-risk contexts include:
github.event.issue.title,github.event.issue.bodygithub.event.pull_request.title,github.event.pull_request.body,.head.ref,.head.labelgithub.event.comment.body,github.event.review.bodygithub.event.pages.*.page_name,github.event.commits.*.message,github.event.head_commit.*github.head_refand anygithub.event.*field a fork author can set
Read references/injection.md for the complete sink list and the safe-pattern fixes.
Step 3 — Check Privileged Triggers Don't Execute Untrusted Code
If a pull_request_target or workflow_run workflow checks out PR/fork code
(ref: ${{ github.event.pull_request.head.sha }}) and then runs it (build, test, install
scripts, npm install with lifecycle scripts, etc.), that is remote code execution against a
privileged token. Flag it as CRITICAL. The safe pattern is to split into two workflows: an
unprivileged pull_request workflow that runs the untrusted code, and a privileged
workflow_run workflow that only consumes its results.
Step 4 — Audit permissions:
If there is no
permissions:block, the workflow inherits the repository default, which may be read/write to everything. Flag it.Recommend a top-level
permissions: {}(deny-all) orcontents: read, then grant the minimum per job (e.g.pull-requests: writeonly on the job that comments).Flag any
permissions: write-allor broadwritescopes that the steps don't actually need.
Read references/permissions-and-tokens.md for the per-scope guidance and OIDC setup.
Step 5 — Audit Action References (Supply Chain)
For every uses::
Third-party actions (not
actions/*orgithub/*) MUST be pinned to a full 40-character commit SHA, not a tag or branch. Tags and branches are mutable; a compromised upstream action can rewritev1to malicious code that runs with your token and secrets.First-party
actions/*are lower risk but SHA-pinning is still the hardened recommendation.Flag
@main,@master, or any branch reference as HIGH — that is "latest" and can change under you at any time.Note the human-readable version in a trailing comment:
uses: foo/bar@<sha> # v2.1.0.
Read references/supply-chain.md for pinning, Dependabot for actions, and artifact/cache risks.
Step 6 — Check Secret and Output Handling
No secrets echoed, printed, or written to logs; no
set -x/bash -xin steps that touch secrets.Secrets must not be passed to steps that run untrusted code or to untrusted third-party actions.
Untrusted multiline data written to
$GITHUB_ENVor$GITHUB_OUTPUTcan inject environment variables or step outputs — use the random-delimiter heredoc form and never write raw user input.actions/checkoutleaves a token on disk by default; setpersist-credentials: falsewhen the job later runs untrusted code.
Step 7 — Produce the Report
Output findings using the format in references/report-format.md: a severity summary table first,
then grouped findings with file, the exact offending YAML, the risk in plain English, and a
concrete before/after fix. Never auto-apply changes — present them for review.
Severity Guide
| Severity | Meaning | Example |
|---|---|---|
| 🔴 CRITICAL | Token/secret theft or RCE reachable by an outside contributor | pull_request_target checking out and running fork code; ${{ github.event.* }} in a run: on a privileged trigger |
| 🟠 HIGH | Exploitable supply-chain or scope problem | Third-party action on a mutable tag/branch; write-all permissions; injection sink on issue_comment |
| 🟡 MEDIUM | Risk under conditions or chaining | Missing permissions: block; secret reachable by a non-fork PR author |
| 🔵 LOW | Hardening gap, low direct risk | First-party action not SHA-pinned; persist-credentials left default on a non-privileged job |
| ⚪ INFO | Observation, not a vulnerability | Version comment missing next to a pinned SHA |
Output Rules
Always show a findings summary table (counts by severity) first.
Group by issue type, not by file.
Be exact — quote the offending line and give the line location.
Always pair every CRITICAL/HIGH with a concrete corrected YAML snippet.
Never claim a fork
pull_requestis dangerous just because it runs untrusted code — it has no secrets and a read-only token. Reserve CRITICAL for the privileged triggers.If the workflow is already hardened, say so and list what was checked.
Reference Files
Load these as needed:
references/triggers-and-privilege.md— Trust matrix for every trigger, whypull_request_targetandworkflow_runare privileged, and the two-workflow safe pattern.Search patterns:
pull_request_target,workflow_run,issue_comment,fork,secrets,read-only token,trust boundary
references/injection.md— Full list of attacker-controllable${{ }}contexts and theenv:-variable safe pattern for each sink (run,github-script, action inputs).Search patterns:
script injection,github.event,head_ref,issue title,env,intermediate variable,actions/github-script
references/permissions-and-tokens.md—GITHUB_TOKENscopes, least-privilegepermissions:recipes per job type, and OIDC for cloud auth instead of long-lived secrets.Search patterns:
permissions,GITHUB_TOKEN,write-all,contents: read,id-token,OIDC,least privilege
references/supply-chain.md— SHA-pinning third-party actions, Dependabot forgithub-actions, artifact and cache poisoning acrossworkflow_run, and self-hosted runner exposure.Search patterns:
SHA pin,uses,mutable tag,Dependabot,download-artifact,cache,self-hosted runner
references/report-format.md— Output template: summary table, finding cards, and before/after remediation blocks.Search patterns:
report,format,finding,summary,remediation,before,after
Files
- ATTRIBUTION.mdAdded by AutoGineer907 B
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md9.6 KiB
- references/injection.md3.0 KiB
- references/permissions-and-tokens.md2.7 KiB
- references/report-format.md1.9 KiB
- references/supply-chain.md2.9 KiB
- references/triggers-and-privilege.md3.3 KiB
Requirements and compatibility
Written for: GitHub Copilot
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Node.js
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- First committed by
AmirhosseinHonardoust
- Publisher
- GitHub (Official)
- Distributed by
- GitHub
- Source
- github/awesome-copilot · skills/github-actions-hardening · commit 797337f
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Contributors
- AmirhosseinHonardoust
AutoGineer is not affiliated with or endorsed by AmirhosseinHonardoust or GitHub.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download github-actions-hardening.zip