{"id":"ec27e639-5e8e-4ec6-a9e2-99397ff51edf","shortId":"MQmBmJ","kind":"skill","title":"gha-security-review","tagline":"Find exploitable vulnerabilities in GitHub Actions workflows. Every finding MUST include a concrete exploitation scenario — if you can't build the attack, don't report it.","description":"<!--\nAttack patterns and real-world examples sourced from the HackerBot Claw campaign analysis\nby StepSecurity (2025): https://www.stepsecurity.io/blog/hackerbot-claw-github-actions-exploitation\n-->\n\n# GitHub Actions Security Review\n\nFind exploitable vulnerabilities in GitHub Actions workflows. Every finding MUST include a concrete exploitation scenario — if you can't build the attack, don't report it.\n\nThis skill encodes attack patterns from real GitHub Actions exploits — not generic CI/CD theory.\n\n## When to Use\n- You are reviewing GitHub Actions workflows for exploitable security issues.\n- The task requires tracing a concrete attack path from an external attacker to workflow execution or secret exposure.\n- You need a security review of workflow files, composite actions, or workflow-related scripts with evidence-based findings only.\n\n## Scope\n\nReview the workflows provided (file, diff, or repo). Research the codebase as needed to trace complete attack paths before reporting.\n\n### Files to Review\n\n- `.github/workflows/*.yml` — all workflow definitions\n- `action.yml` / `action.yaml` — composite actions in the repo\n- `.github/actions/*/action.yml` — local reusable actions\n- Config files loaded by workflows: `CLAUDE.md`, `AGENTS.md`, `Makefile`, shell scripts under `.github/`\n\n### Out of Scope\n\n- Workflows in other repositories (only note the dependency)\n- GitHub App installation permissions (note if relevant)\n\n## Threat Model\n\nOnly report vulnerabilities exploitable by an **external attacker** — someone **without** write access to the repository. The attacker can open PRs from forks, create issues, and post comments. They cannot push to branches, trigger `workflow_dispatch`, or trigger manual workflows.\n\n**Do not flag** vulnerabilities that require write access to exploit:\n- `workflow_dispatch` input injection — requires write access to trigger\n- Expression injection in `push`-only workflows on protected branches\n- `workflow_call` input injection where all callers are internal\n- Secrets in `workflow_dispatch`/`schedule`-only workflows\n\n## Confidence\n\nReport only **HIGH** and **MEDIUM** confidence findings. Do not report theoretical issues.\n\n| Confidence | Criteria | Action |\n|---|---|---|\n| **HIGH** | Traced the full attack path, confirmed exploitable | Report with exploitation scenario and fix |\n| **MEDIUM** | Attack path partially confirmed, uncertain link | Report as needs verification |\n| **LOW** | Theoretical or mitigated elsewhere | Do not report |\n\nFor each HIGH finding, provide all five elements:\n\n1. **Entry point** — How does the attacker get in? (fork PR, issue comment, branch name, etc.)\n2. **Payload** — What does the attacker send? (actual code/YAML/input)\n3. **Execution mechanism** — How does the payload run? (expression expansion, checkout + script, etc.)\n4. **Impact** — What does the attacker gain? (token theft, code execution, repo write access)\n5. **PoC sketch** — Concrete steps an attacker would follow\n\nIf you cannot construct all five, report as MEDIUM (needs verification).\n\n---\n\n## Step 1: Classify Triggers and Load References\n\nFor each workflow, identify triggers and load the appropriate reference:\n\n| Trigger / Pattern | Load Reference |\n|---|---|\n| `pull_request_target` | `references/pwn-request.md` |\n| `issue_comment` with command parsing | `references/comment-triggered-commands.md` |\n| `${{ }}` in `run:` blocks | `references/expression-injection.md` |\n| PATs / deploy keys / elevated credentials | `references/credential-escalation.md` |\n| Checkout PR code + config file loading | `references/ai-prompt-injection-via-ci.md` |\n| Third-party actions (especially unpinned) | `references/supply-chain.md` |\n| `permissions:` block or secrets usage | `references/permissions-and-secrets.md` |\n| Self-hosted runners, cache/artifact usage | `references/runner-infrastructure.md` |\n| Any confirmed finding | `references/real-world-attacks.md` |\n\nLoad references selectively — only what's relevant to the triggers found.\n\n## Step 2: Check for Vulnerability Classes\n\n### Check 1: Pwn Request\n\nDoes the workflow use `pull_request_target` AND check out fork code?\n- Look for `actions/checkout` with `ref:` pointing to PR head\n- Look for local actions (`./.github/actions/`) that would come from the fork\n- Check if any `run:` step executes code from the checked-out PR\n\n### Check 2: Expression Injection\n\nAre `${{ }}` expressions used inside `run:` blocks in externally-triggerable workflows?\n- Map every `${{ }}` expression in every `run:` step\n- Confirm the value is attacker-controlled (PR title, branch name, comment body — not numeric IDs, SHAs, or repository names)\n- Confirm the expression is in a `run:` block, not `if:`, `with:`, or job-level `env:`\n\n### Check 3: Unauthorized Command Execution\n\nDoes an `issue_comment`-triggered workflow execute commands without authorization?\n- Is there an `author_association` check?\n- Can any GitHub user trigger the command?\n- Does the command handler also use injectable expressions?\n\n### Check 4: Credential Escalation\n\nAre elevated credentials (PATs, deploy keys) accessible to untrusted code?\n- What's the blast radius of each secret?\n- Could a compromised workflow steal long-lived tokens?\n\n### Check 5: Config File Poisoning\n\nDoes the workflow load configuration from PR-supplied files?\n- AI agent instructions: `CLAUDE.md`, `AGENTS.md`, `.cursorrules`\n- Build configuration: `Makefile`, shell scripts\n\n### Check 6: Supply Chain\n\nAre third-party actions securely pinned?\n\n### Check 7: Permissions and Secrets\n\nAre workflow permissions minimal? Are secrets properly scoped?\n\n### Check 8: Runner Infrastructure\n\nAre self-hosted runners, caches, or artifacts used securely?\n\n## Safe Patterns (Do Not Flag)\n\nBefore reporting, check if the pattern is actually safe:\n\n| Pattern | Why Safe |\n|---|---|\n| `pull_request_target` WITHOUT checkout of fork code | Never executes attacker code |\n| `${{ github.event.pull_request.number }}` in `run:` | Numeric only — not injectable |\n| `${{ github.repository }}` / `github.repository_owner` | Repo owner controls this |\n| `${{ secrets.* }}` | Not an expression injection vector |\n| `${{ }}` in `if:` conditions | Evaluated by Actions runtime, not shell |\n| `${{ }}` in `with:` inputs | Passed as string parameters, not shell-evaluated |\n| Actions pinned to full SHA | Immutable reference |\n| `pull_request` trigger (not `_target`) | Runs in fork context with read-only token |\n| Any expression in `workflow_dispatch`/`schedule`/`push` to protected branches | Requires write access — outside threat model |\n\n**Key distinction:** `${{ }}` is dangerous in `run:` blocks (shell expansion) but safe in `if:`, `with:`, and `env:` at the job/step level (Actions runtime evaluation).\n\n## Step 3: Validate Before Reporting\n\nBefore including any finding, read the actual workflow YAML and trace the complete attack path:\n\n1. **Read the full workflow** — don't rely on grep output alone\n2. **Trace the trigger** — confirm the event and check `if:` conditions that gate execution\n3. **Trace the expression/checkout** — confirm it's in a `run:` block or actually references fork code\n4. **Confirm attacker control** — verify the value maps to something an external attacker sets\n5. **Check existing mitigations** — env var wrapping, author_association checks, restricted permissions, SHA pinning\n\nIf any link is broken, mark MEDIUM (needs verification) or drop the finding.\n\n**If no checks produced a finding, report zero findings. Do not invent issues.**\n\n## Step 4: Report Findings\n\n````markdown\n## GitHub Actions Security Review\n\n### Findings\n\n#### [GHA-001] [Title] (Severity: Critical/High/Medium)\n- **Workflow**: `.github/workflows/release.yml:15`\n- **Trigger**: `pull_request_target`\n- **Confidence**: HIGH — confirmed through attack path tracing\n- **Exploitation Scenario**:\n  1. [Step-by-step attack]\n- **Impact**: [What attacker gains]\n- **Fix**: [Code that fixes the issue]\n\n### Needs Verification\n[MEDIUM confidence items with explanation of what to verify]\n\n### Reviewed and Cleared\n[Workflows reviewed and confirmed safe]\n````\n\nIf no findings: \"No exploitable vulnerabilities identified. All workflows reviewed and cleared.\"\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.","tags":["gha","security","review","antigravity","awesome","skills","sickn33","agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding"],"capabilities":["skill","source-sickn33","skill-gha-security-review","topic-agent-skills","topic-agentic-skills","topic-ai-agent-skills","topic-ai-agents","topic-ai-coding","topic-ai-workflows","topic-antigravity","topic-antigravity-skills","topic-claude-code","topic-claude-code-skills","topic-codex-cli","topic-codex-skills"],"categories":["antigravity-awesome-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/sickn33/antigravity-awesome-skills/gha-security-review","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add sickn33/antigravity-awesome-skills","source_repo":"https://github.com/sickn33/antigravity-awesome-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 34768 github stars · SKILL.md body (8,506 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-23T18:51:22.173Z","embedding":null,"createdAt":"2026-04-18T21:37:52.544Z","updatedAt":"2026-04-23T18:51:22.173Z","lastSeenAt":"2026-04-23T18:51:22.173Z","tsv":"'-001':995 '/.github/actions':530 '/action.yml':164 '1':340,413,502,888,1015 '15':1001 '2':356,496,551,900 '3':365,609,869,914 '4':378,645,930,985 '5':392,676,944 '6':702 '7':713 '8':726 'access':211,246,255,391,654,841 'action':10,32,40,69,82,115,159,167,298,463,529,709,793,808,865,990 'action.yaml':157 'action.yml':156 'actions/checkout':519 'actual':363,751,879,926 'agent':691 'agents.md':174,694 'ai':690 'alon':899 'also':640 'app':192 'appropri':427 'artifact':736 'ask':1095 'associ':627,952 'attack':26,56,64,94,99,144,207,216,303,314,346,361,383,398,577,766,886,932,942,1010,1020,1023 'attacker-control':576 'author':622,626,951 'base':124 'blast':661 'block':445,468,559,599,851,924 'bodi':584 'boundari':1103 'branch':231,266,353,581,838 'broken':962 'build':24,54,696 'cach':734 'cache/artifact':477 'call':268 'caller':273 'cannot':228,403 'chain':704 'check':497,501,513,537,547,550,608,628,644,675,701,712,725,746,908,945,953,973 'checked-out':546 'checkout':375,453,760 'ci/cd':73 'clarif':1097 'class':500 'classifi':414 'claude.md':173,693 'clear':1044,1061,1070 'code':387,455,516,543,657,763,767,929,1026 'code/yaml/input':364 'codebas':138 'come':533 'command':440,611,620,635,638 'comment':226,352,438,583,616 'complet':143,885 'composit':114,158 'compromis':668 'concret':17,47,93,395 'condit':790,910 'confid':283,289,296,1006,1034 'config':168,456,677 'configur':684,697 'confirm':305,317,481,572,592,904,918,931,1008,1048 'construct':404 'context':823 'control':578,780,933 'could':666 'creat':222 'credenti':451,646,650 'criteria':297,1106 'critical/high/medium':998 'cursorrul':695 'danger':848 'definit':155 'depend':190 'deploy':448,652 'describ':1074 'diff':133 'dispatch':234,250,279,833 'distinct':846 'drop':968 'element':339 'elev':450,649 'elsewher':328 'encod':63 'entri':341 'env':607,860,948 'environ':1086 'environment-specif':1085 'escal':647 'especi':464 'etc':355,377 'evalu':791,807,867 'event':906 'everi':12,42,566,569 'evid':123 'evidence-bas':122 'execut':102,366,388,542,612,619,765,913 'exist':946 'expans':374,853 'expert':1091 'explan':1037 'exploit':6,18,36,48,70,85,203,248,306,309,1013,1054 'exposur':105 'express':258,373,552,555,567,594,643,785,830 'expression/checkout':917 'extern':98,206,562,941 'externally-trigger':561 'file':113,132,148,169,457,678,689 'find':5,13,35,43,125,290,335,482,876,970,976,979,987,993,1052 'five':338,406 'fix':312,1025,1028 'flag':241,743 'follow':400 'fork':221,349,515,536,762,822,928 'found':494 'full':302,811,891 'gain':384,1024 'gate':912 'generic':72 'get':347 'gha':2,994 'gha-security-review':1 'github':9,31,39,68,81,179,191,631,989 'github.event.pull_request.number':768 'github.repository':775,776 'github/actions':163 'github/workflows':151 'github/workflows/release.yml':1000 'grep':897 'handler':639 'head':525 'high':286,299,334,1007 'host':475,732 'id':587 'identifi':422,1056 'immut':813 'impact':379,1021 'includ':15,45,874 'infrastructur':728 'inject':252,259,270,553,642,774,786 'input':251,269,799,1100 'insid':557 'instal':193 'instruct':692 'intern':275 'invent':982 'issu':87,223,295,351,437,615,983,1030 'item':1035 'job':605 'job-level':604 'job/step':863 'key':449,653,845 'level':606,864 'limit':1062 'link':319,960 'live':673 'load':170,417,425,431,458,484,683 'local':165,528 'long':672 'long-liv':671 'look':517,526 'low':324 'makefil':175,698 'manual':237 'map':565,937 'mark':963 'markdown':988 'match':1071 'mechan':367 'medium':288,313,409,964,1033 'minim':720 'miss':1108 'mitig':327,947 'model':199,844 'must':14,44 'name':354,582,591 'need':107,140,322,410,965,1031 'never':764 'note':188,195 'numer':586,771 'open':218 'output':898,1080 'outsid':842 'owner':777,779 'paramet':803 'pars':441 'parti':462,708 'partial':316 'pass':800 'pat':447,651 'path':95,145,304,315,887,1011 'pattern':65,430,740,749,753 'payload':357,371 'permiss':194,467,714,719,955,1101 'pin':711,809,957 'poc':393 'point':342,522 'poison':679 'post':225 'pr':350,454,524,549,579,687 'pr-suppli':686 'produc':974 'proper':723 'protect':265,837 'provid':131,336 'prs':219 'pull':433,509,756,815,1003 'push':229,261,835 'pwn':503 'radius':662 'read':826,877,889 'read-on':825 'real':67 'ref':521 'refer':418,428,432,485,814,927 'references/ai-prompt-injection-via-ci.md':459 'references/comment-triggered-commands.md':442 'references/credential-escalation.md':452 'references/expression-injection.md':446 'references/permissions-and-secrets.md':472 'references/pwn-request.md':436 'references/real-world-attacks.md':483 'references/runner-infrastructure.md':479 'references/supply-chain.md':466 'relat':119 'relev':197,490 'reli':895 'repo':135,162,389,778 'report':29,59,147,201,284,293,307,320,331,407,745,872,977,986 'repositori':186,214,590 'request':434,504,510,757,816,1004 'requir':90,244,253,839,1099 'research':136 'restrict':954 'reusabl':166 'review':4,34,80,110,128,150,992,1042,1046,1059,1092 'run':372,444,540,558,570,598,770,820,850,923 'runner':476,727,733 'runtim':794,866 'safe':739,752,755,855,1049 'safeti':1102 'scenario':19,49,310,1014 'schedul':280,834 'scope':127,182,724,1073 'script':120,177,376,700 'secret':104,276,470,665,716,722,782 'secur':3,33,86,109,710,738,991 'select':486 'self':474,731 'self-host':473,730 'send':362 'set':943 'sever':997 'sha':812,956 'shas':588 'shell':176,699,796,806,852 'shell-evalu':805 'sketch':394 'skill':62,1065 'skill-gha-security-review' 'someon':208 'someth':939 'source-sickn33' 'specif':1087 'steal':670 'step':396,412,495,541,571,868,984,1017,1019 'step-by-step':1016 'stop':1093 'string':802 'substitut':1083 'success':1105 'suppli':688,703 'target':435,511,758,819,1005 'task':89,1069 'test':1089 'theft':386 'theoret':294,325 'theori':74 'third':461,707 'third-parti':460,706 'threat':198,843 'titl':580,996 'token':385,674,828 'topic-agent-skills' 'topic-agentic-skills' 'topic-ai-agent-skills' 'topic-ai-agents' 'topic-ai-coding' 'topic-ai-workflows' 'topic-antigravity' 'topic-antigravity-skills' 'topic-claude-code' 'topic-claude-code-skills' 'topic-codex-cli' 'topic-codex-skills' 'trace':91,142,300,883,901,915,1012 'treat':1078 'trigger':232,236,257,415,423,429,493,563,617,633,817,903,1002 'unauthor':610 'uncertain':318 'unpin':465 'untrust':656 'usag':471,478 'use':77,508,556,641,737,1063 'user':632 'valid':870,1088 'valu':574,936 'var':949 'vector':787 'verif':323,411,966,1032 'verifi':934,1041 'vulner':7,37,202,242,499,1055 'without':209,621,759 'workflow':11,41,83,101,112,118,130,154,172,183,233,238,249,263,267,278,282,421,507,564,618,669,682,718,832,880,892,999,1045,1058 'workflow-rel':117 'would':399,532 'wrap':950 'write':210,245,254,390,840 'yaml':881 'yml':152 'zero':978","prices":[{"id":"6f2ec70f-8326-49a4-afa9-9325e316b4a3","listingId":"ec27e639-5e8e-4ec6-a9e2-99397ff51edf","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"sickn33","category":"antigravity-awesome-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T21:37:52.544Z"}],"sources":[{"listingId":"ec27e639-5e8e-4ec6-a9e2-99397ff51edf","source":"github","sourceId":"sickn33/antigravity-awesome-skills/gha-security-review","sourceUrl":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/gha-security-review","isPrimary":false,"firstSeenAt":"2026-04-18T21:37:52.544Z","lastSeenAt":"2026-04-23T18:51:22.173Z"}],"details":{"listingId":"ec27e639-5e8e-4ec6-a9e2-99397ff51edf","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"sickn33","slug":"gha-security-review","github":{"repo":"sickn33/antigravity-awesome-skills","stars":34768,"topics":["agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity","antigravity-skills","claude-code","claude-code-skills","codex-cli","codex-skills","cursor","cursor-skills","developer-tools","gemini-cli","gemini-skills","kiro","mcp","skill-library"],"license":"mit","html_url":"https://github.com/sickn33/antigravity-awesome-skills","pushed_at":"2026-04-23T06:41:03Z","description":"Installable GitHub library of 1,400+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and more. Includes installer CLI, bundles, workflows, and official/community skill collections.","skill_md_sha":"8f7a88da2f14f7d915daf6c69e6fe3f065de38ba","skill_md_path":"skills/gha-security-review/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/gha-security-review"},"layout":"multi","source":"github","category":"antigravity-awesome-skills","frontmatter":{"name":"gha-security-review","description":"Find exploitable vulnerabilities in GitHub Actions workflows. Every finding MUST include a concrete exploitation scenario — if you can't build the attack, don't report it."},"skills_sh_url":"https://skills.sh/sickn33/antigravity-awesome-skills/gha-security-review"},"updatedAt":"2026-04-23T18:51:22.173Z"}}