CVE-2026-59160: @yeger/turbo-graph Unauthenticated Remote Task Execution
A developer tool for visualizing Turborepo task graphs accidentally exposes an unauthenticated HTTP endpoint to the local network, letting any nearby attacker silently run arbitrary build tasks with…

The problem
Two independent bugs combine into the vulnerability. First, packages/turbo-graph/src/index.ts calls .listen(options.port, callback) without passing a hostname, so Node.js defaults to binding on all interfaces (0.0.0.0:29312) instead of loopback only.
Second, the /api/run route in packages/turbo-graph-ui/app/api/run/route.ts has zero authentication. It reads tasks, filter, and force straight from the query string and passes them to spawn(turboBin, ['run', ...tasks], { cwd: dir }). Any host on the same network segment can trigger any task in the victim's turbo.json, including tasks that write files, call cloud CLIs, or run deployment scripts.
Proof of concept
A working proof-of-concept for CVE-2026-59160 in @yeger/turbo-graph, with the exact payload below.
# From any host on the same LAN as a developer running turbo-graph:
curl -N "http://<victim-ip>:29312/api/run?tasks=pwn&force=true"
# The server responds HTTP 200 with a text/event-stream body.
# An SSE 'start' event confirms execution:
# data: {"args":["run","pwn","--ui=stream","--force"]}
# No token, cookie, or credential of any kind is required.The root cause is CWE-306: missing authentication for a critical function. The hostname variable declared at index.ts:19 is only ever used to build the console log URL string. It is never passed to .listen(), so the server is network-exposed by accident, not by design.
Because spawn() is called with an argument array rather than a shell string, classic shell injection characters do not apply. The exploit does not need them: any task name already in turbo.json can be selected directly via the ?tasks= parameter with no escaping or bypass required.
The 2.8.12 patch passes the hostname argument to .listen() so the server binds to 127.0.0.1 only, and adds an authentication check to the /api/run handler so the endpoint is no longer reachable or usable without authorization.
The fix
Upgrade to @yeger/turbo-graph version **2.8.12** or later. The patch binds the embedded Next.js server to 127.0.0.1 (loopback) instead of all interfaces, and adds authentication to the /api/run endpoint. No configuration change can mitigate affected versions; a firewall rule blocking port 29312 from the LAN is a partial workaround only.
Related research
- high · 7.5@typespec/spector Unauthenticated Remote Shutdown via POST /.admin/stop
- high · 8.8CVE-2026-73222CVE-2026-73222: claude-code-templates Unauthenticated OS Command Injection (RCE) in Studio Server
- high · 8.6CVE-2026-56677CVE-2026-56677: 9router Unauthenticated SSRF via OIDC Test Endpoint
- high · 7.5dynatrace-mcp-server Unauthenticated HTTP MCP Tool Invocation