Tailworm · 11 findings · Tailscale 1.104.2 · headscale 0.29.5
Is your tailnet exposed to Tailworm?
A security assessment published 24 to 25 October 2026 reports 11 findings in Tailscale 1.104.2 and headscale 0.29.5. Paste what your own tailnet already tells you and get a ranked verdict for each one, with a review-only fix pack. Nothing on your tailnet changes.
Check your tailnetRead the 11 findings
0 of 11 have a vendor fix. Patch sources last checked 2026-10-29.
01 The findings
-
Tailscale SSH: local Unix-socket forwarding (ssh -L) dials as root
If Tailscale SSH is on for a server and your policy lets another device SSH into it, anyone who takes over that other device can reach root-only services on the server through the SSH session. If Tailscale SSH is off everywhere, this does not apply to you.
-
Tailscale SSH: remote Unix-socket forwarding (ssh -R) replaces root-owned sockets
Same precondition as finding 1: Tailscale SSH on, plus a policy rule that lets a peer in. An attacker on that peer can impersonate root services on the server. Off everywhere means not affected.
-
Tailscale SSH: a race (TOCTOU) defeats the socket-path allowlist
This is why "only allow sockets in the user's own folders" does not protect you. Same precondition as findings 1 and 2. If an attacker gets this far on a tailnet without Tailnet Lock, the report shows they can add their own machine to your tailnet.
-
conn25 app connectors: a user entitlement allows any egress destination
Only matters if you use the experimental conn25 app-connector feature. Classic app connectors are not this finding. If you do use conn25, every user you gave an app to can reach far more than that app.
-
Tailscale SSH: session churn pins memory in the root daemon (OOM loop)
Anyone your policy lets SSH into a node can knock that node's Tailscale offline. The report found no Tailscale-side workaround: the only levers are SSH off or fewer SSH rules.
-
headscale: unauthenticated memory exhaustion and onboarding lockout; DERP client response bomb
Only matters if you run your own headscale control server. On Tailscale's hosted control plane the headscale parts do not apply. The relay part (C3) needs your clients to be pointed at a relay an attacker controls.
-
tailscale serve: a TCP forward to the tailscaled socket exposes the admin API
Check every node that uses
tailscale serve: a TCP forward to a Unix socket, and above all to tailscaled's own socket, must not exist. If you never forward to a Unix socket, this does not apply. -
tailscale serve: the tailscaled-socket guard is checked only at config time
If a serve backend on a node is a Unix socket in a folder other users can write to, that user can redirect it. Root-owned folders are safe; no Unix backends means not affected.
-
Funnel: the funnel node attribute is enforced only by the CLI
A threat-model note: the "funnel" permission in your policy is checked by the tailscale command, not by the daemon. Treat any node with funnel on as internet-facing and know why it is on.
-
TS_SERVE_ALLOW_ALL_INTERFACES exposes serve outside the tunnel
Off by default and set mainly by the Kubernetes operator's experimental ingress. If you never set it, this does not apply.
-
tailscale serve over HTTP/2: app-capability headers can bleed between mounts
Only matters if one serve host:port has several paths that pass different Tailscale app capabilities to your app, and your app trusts that header for authorization.
As of 2026-10-25 Tailscale has published no security bulletin, release note or changelog entry that acknowledges or fixes the Tailworm findings. The latest client is 1.104.2, the version the report tested. Earlier bulletins TS-2026-004 and TS-2026-005 fixed related issues in 1.98; they do not reference Tailworm.
02 Check your tailnet
03 Run it on a node
One POSIX shell script. It runs read-only tailscale commands on the node you choose, prints JSON and sends nothing unless you add --submit.
curl -fsS https://tailnet.geoa.io/cli/geoa-tailnet.sh | sh -s -- --jsoncurl -fsS https://tailnet.geoa.io/cli/geoa-tailnet.sh | sh -s -- --submit https://tailnet.geoa.io/api/node-reportRead it first: /cli/geoa-tailnet.sh. It never reads keys or debug output and never changes a setting. Paste its JSON into the node report box above.
04 Ask your agent
The same audit as an MCP server: ask Claude Code, Cursor or Codex to check your tailnet and explain a finding with its source line.
Claude Code
claude mcp add --transport http geoa-tailnet https://tailnet.geoa.io/mcpbash <(curl -s https://tailnet.geoa.io/plugin/install.sh)Then ask /geoa-tailnet TW-01, /geoa-tailnet check or /geoa-tailnet fix. Full setup and example prompts.
Cursor
{
"mcpServers": {
"geoa-tailnet": {
"url": "https://tailnet.geoa.io/mcp"
}
}
}Project-level file; use ~/.cursor/mcp.json for every project. Cursor lists the 8 tools under MCP in settings.
Codex
[mcp_servers.geoa-tailnet]
url = "https://tailnet.geoa.io/mcp"Restart Codex; /mcp shows geoa-tailnet with its tools.
Any agent
Set up the Geoa Tailnet Guard MCP server for me: name geoa-tailnet, transport Streamable HTTP, URL https://tailnet.geoa.io/mcp, no login. Confirm it lists the tools list_findings, explain_finding, audit_status_json, audit_policy, audit_node_report, propose_fix, patch_status, watch_tailnet, then explain finding TW-01 with its source citation.Works with any MCP client that speaks Streamable HTTP. Tools: list_findings, explain_finding, audit_status_json, audit_policy, audit_node_report, propose_fix, patch_status, watch_tailnet.