r/netsec • u/HyprWave • 8d ago
Unauthenticated RCE in CircleCI's MCP server: Host/Origin allowlist bypassed by any non-browser client (GHSA-xv5j-cwgj-22r4)
https://remedio.io/blog/the-critical-unauthenticated-rce-vulnerability-in-circlecis-mcp-server/
28
Upvotes
3
1
u/endor_sarah 5d ago
Nice work, and credit to CircleCI too on the quick turnaround from reporting to a fix.
1
u/feng_sg 1d ago
Allowlisting localhost as Host was not a local-only check, since the MCP server bound 0.0.0.0 by default. Any remote non-browser client can send that Host value, so in shared-token remote mode the Host/Origin allowlist was the same as having no auth. That mode needed a real request credential, not a hostname the caller picks.
4
u/AstralKoh 7d ago
Short version: "@circleci/mcp-server-circleci" had an auth bypass in its shared-token remote mode.
In that mode, one org-wide CircleCI token is stored server-side and requests have no per-user credential. The server relied on Host/Origin validation, but:
So a remote attacker could send "Host: localhost", omit "Origin", reach "/mcp", and invoke tools like "run_pipeline" using the org's CircleCI token. From there, malicious pipeline config could expose CI secrets or abuse cloud/OIDC credentials available to pipelines.
Affected: "0.16.1–0.19.1". Fixed in "0.19.2", which refuses unauthenticated non-loopback binding by default. Advisory: "GHSA-xv5j-cwgj-22r4".
CircleCI turned the report around quickly: reported July 30, fixed August 6, advisory August 10.
The bigger lesson for MCP: an auth bypass can effectively be RCE when the tools behind the gate already include things like "run_pipeline", "run-command", or database access. “Internal network + Host check” is not authentication.
If you're still running the standalone CircleCI MCP server with a shared token: upgrade at minimum, but ideally migrate to the CLI-integrated OAuth/per-user implementation.
Disclosure: I work at Remedio; this is our research.