AI and data stack advisories

Severe, 6 weeks1496Projects326

1496 severe, 6 weeks · 326 projects

GitHubGHSA-2cwf-x2h8-mqj5

gh-aw: unauthenticated prompt-injection to code execution in the shipped ai-moderator workflow

GitHub

Published Aug 7, 2026

Medium6.5
Fix: upgrade to v0.86.1 or later
GitHub advisory

Summary

The shipped ai-moderator.md workflow, which runs on github/gh-aw itself,

combines four settings that together hand an unauthenticated GitHub user code

execution in the agent job. The agent job holds GITHUB_TOKEN and the engine API

keys. The compiler emits no warning for this combination. This is live on

github/gh-aw right now and reachable by any GitHub account with no special

access. It is the most immediately exploitable of the issues I found in this

review of gh-aw.

I verified this against current main at commit 966ccb8 (2026-07-12). It was

first verified at bdfdb8e (2026-06-24, ~v0.80.9); the intervening commits did

not change any of the four ingredients.

Details

gh-aw treats issue/PR/comment content from arbitrary GitHub users as

attacker-controlled, and its compiler normally env-indirects those expressions

out of shell contexts. This workflow disables the controls that enforce that

model. The four ingredients:

1. roles: all removes the activation gate. needsRoleCheck in

pkg/workflow/role_checks.go:348-353 returns false when roles is ["all"],

so the compiled lock has no check_membership step. In the compiled

ai-moderator.lock.yml the activation condition is just

rate_limit_ok && skip_roles_ok && skip_bots_ok. The workflow triggers on

issues: [opened], issue_comment: [created], and pull_request: [opened]...

Affected versions

PackageAffectedFixed in
github/gh-aw
Product
< v0.86.1v0.86.1
Details and references

### Summary The shipped `ai-moderator.md` workflow, which runs on github/gh-aw itself, combines four settings that together hand an unauthenticated GitHub user code execution in the agent job. The agent job holds GITHUB_TOKEN and the engine API keys. The compiler emits no warning for this combination. This is live on github/gh-aw right now and reachable by any GitHub account with no special access. It is the most immediately exploitable of the issues I found in this review of gh-aw. I verified this against current `main` at commit `966ccb8` (2026-07-12). It was first verified at `bdfdb8e` (2026-06-24, ~v0.80.9); the intervening commits did not change any of the four ingredients. ### Details gh-aw treats issue/PR/comment content from arbitrary GitHub users as attacker-controlled, and its compiler normally env-indirects those expressions out of shell contexts. This workflow disables the controls that enforce that model. The four ingredients: 1. `roles: all` removes the activation gate. `needsRoleCheck` in `pkg/workflow/role_checks.go:348-353` returns false when roles is `["all"]`, so the compiled lock has no `check_membership` step. In the compiled `ai-moderator.lock.yml` the activation condition is just `rate_limit_ok && skip_roles_ok && skip_bots_ok`. The workflow triggers on `issues: [opened]`, `issue_comment: [created]`, and `pull_request: [opened]` with `forks: "*"`, all reachable by an external account. 2. `tools.github.min-integrity: none` defeats the author-association filter that public repos otherwise default to `approved` (`actions/setup/js/determine_automatic_lockdown.cjs:57`); a configured value is never overridden (`:61-67`). `threat-detection: false` removes the injection pre-screen. The prompt then instructs the agent to fetch raw content: "Use the GitHub MCP server tools to fetch the original context ... unsanitized content directly from GitHub API" and "Do NOT use the pre-sanitized text from the activation job". 3. `engine: codex` compiles to `codex exec --dangerously-bypass-approvals-and-sandbox` (`pkg/workflow/codex_engine.go:238`), so the agent auto-executes shell with no approval. The other auto-executing engines are equivalent: gemini emits `--yolo` (`pkg/workflow/gemini_engine.go:181`), copilot emits `--allow-all-tools` (`pkg/workflow/copilot_engine_tools.go:78`). The AWF firewall around the engine filters network egress only, not local execution. 4. An issue/PR/comment trigger reachable by arbitrary users (above). There is no compile-time diagnostic for open activation + `min-integrity: none` + an auto-executing engine. ### PoC I reproduced the full chain on my own repo on a real runner: an external issue activates the agent with no membership check, the raw issue body is built into the prompt, and the auto-approved agent runs shell via the engine and posts back to the issue. I used the gemini engine for the live run because I had a free key rather than codex credits; the mechanism is engine-independent, and the shipped ai-moderator uses codex. Markers were benign (`PWNED_*`). ### Impact Any GitHub account can drive shell execution inside the agent job on a repo running this pattern. Containment on most adopters: `--exclude-env` strips engine/MCP keys, the agent token is read-only, egress is allowlisted. The last step is XPIA (the model must follow the payload). Every control that would normally make that unreliable is disabled by this configuration, the payload surface is the whole body/diff, and the prompt instructs the model to trust raw content. CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:L (7.5). Up to 9.1 (Critical) where the agent has an arbitrary-shell tool. ### Suggested fix Fail the build, or emit a hard warning, when open activation is combined with `min-integrity: none`/`unapproved` and an auto-executing engine. Stop shipping samples that instruct th

CVSS 3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:L
Severity from
GitHub (reviewed advisory)
Weakness
CWE-94, CWE-1188

More GitHub advisories

All GitHub