GHSL-2026-184: Ungated MCP `mcp-inspect` executes attacker-declared stdio command (chained with ungated `add`)
GitHub Security Lab (GHSL) Vulnerability Report, gh-aw: GHSL-2026-184
The [GitHub Security Lab](https://securitylab.github.com) team has identified a potential security vulnerability in [gh-aw](https://github.com/github/gh-aw).
We are committed to working with you to help resolve this issue. In this report you will find everything you need to effectively coordinate a resolution of this issue with the GHSL team.
If at any point you have concerns or questions about this process, please do not hesitate to reach out to us at securitylab@github.com (please include GHSL-2026-184 as a reference). See also [this blog post](https://github.blog/2022-04-22-removing-the-stigma-of-a-cve/) written by GitHub's Advisory Curation team which explains what CVEs and advisories are, why they are important to track vulnerabilities and keep downstream users informed, the CVE assigning process, and how they are used to keep open source software secure.
If you are _NOT_ the correct point of contact for this report, please let us know!
Summary
The MCP server's file-writing and process-launching tools (add, update, fix, compile, mcp-inspect) are not authorization-gated, and mcp-inspect executes an arbitrary command/args declared in a workflow file after only an exec.LookPath existence check. Chained with the ungated add tool, an MCP client can plant a workflow declaring...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| gh-aw Product | < v0.91.12 | v0.91.12 |
Details and references
# GitHub Security Lab (GHSL) Vulnerability Report, gh-aw: `GHSL-2026-184` The [GitHub Security Lab](https://securitylab.github.com) team has identified a potential security vulnerability in [gh-aw](https://github.com/github/gh-aw). We are committed to working with you to help resolve this issue. In this report you will find everything you need to effectively coordinate a resolution of this issue with the GHSL team. If at any point you have concerns or questions about this process, please do not hesitate to reach out to us at `securitylab@github.com` (please include `GHSL-2026-184` as a reference). See also [this blog post](https://github.blog/2022-04-22-removing-the-stigma-of-a-cve/) written by GitHub's Advisory Curation team which explains what CVEs and advisories are, why they are important to track vulnerabilities and keep downstream users informed, the CVE assigning process, and how they are used to keep open source software secure. If you are _NOT_ the correct point of contact for this report, please let us know! ## Summary The MCP server's file-writing and process-launching tools (`add`, `update`, `fix`, `compile`, `mcp-inspect`) are not authorization-gated, and `mcp-inspect` executes an arbitrary command/args declared in a workflow file after only an `exec.LookPath` existence check. Chained with the ungated `add` tool, an MCP client can plant a workflow declaring a stdio MCP server and then invoke `mcp-inspect` to obtain arbitrary command execution as the operator. ## Project gh-aw ## Tested Version 846c520 ## Details ### Ungated MCP `mcp-inspect` executes attacker-declared stdio command (chained with ungated `add`) (`GHSL-2026-184`) `createMCPServer` ([pkg/cli/mcp_server.go:19-99](https://github.com/github/gh-aw/blob/846c5209f8ac443380ab8f0830d858161a10737f/pkg/cli/mcp_server.go#L19-L99)) registers ten MCP tools. The only authorization gate, `checkActorPermission` ([pkg/cli/mcp_permissions.go:68-136](https://github.com/github/gh-aw/blob/846c5209f8ac443380ab8f0830d858161a10737f/pkg/cli/mcp_permissions.go#L68-L136)), is invoked only from `logs`, `audit` and `audit-diff` handlers. The file-writing/exec management tools `add`, `update`, `fix`, `compile` and `mcp-inspect` have no authorization gate at all. The `mcp-inspect` tool handler ([pkg/cli/mcp_tools_readonly.go:315-391](https://github.com/github/gh-aw/blob/846c5209f8ac443380ab8f0830d858161a10737f/pkg/cli/mcp_tools_readonly.go#L315-L391)) ultimately invokes `connectStdioMCPServer` in `pkg/cli/mcp_inspect_mcp.go`, which parses the `mcp` configuration out of a local workflow file and executes the declared command — the [`exec.LookPath` check at :145](https://github.com/github/gh-aw/blob/846c5209f8ac443380ab8f0830d858161a10737f/pkg/cli/mcp_inspect_mcp.go#L145) and the [`exec.CommandContext` call at :160](https://github.com/github/gh-aw/blob/846c5209f8ac443380ab8f0830d858161a10737f/pkg/cli/mcp_inspect_mcp.go#L160): ```go // pkg/cli/mcp_inspect_mcp.go:145 if _, err := exec.LookPath(config.Command); err != nil { return fmt.Errorf("command not found: %s", config.Command) } // ... // pkg/cli/mcp_inspect_mcp.go:160 cmd = exec.CommandContext(ctx, config.Command, config.Args...) ``` `exec.LookPath` is only an existence check — there is no allow-list of permitted MCP commands, so `command: /bin/sh` with `args: ["-c", "..."]` passes trivially. Because `add` ([pkg/cli/mcp_tools_management.go:23-83](https://github.com/github/gh-aw/blob/846c5209f8ac443380ab8f0830d858161a10737f/pkg/cli/mcp_tools_management.go#L23-L83)) is likewise ungated, an MCP client can first plant a workflow file under `.github/workflows/` whose YAML frontmatter declares a stdio MCP server pointing at an arbitrary command ([`ScanMarkdownSecurity` in pkg/workflow/markdown_security_scanner.go:78](https://github.com/github/gh-aw/blob/846c5209f8ac443380ab8f0830d858161a10737f/pkg/workflow/markdown_security_scanner.go#L78) strips and does not scan the frontma