Tailworm — Tailscale SSH vulnerability cluster
Tailworm is the name Cyberdione Labs gave a security assessment of Tailscale v1.104.2 and the self-hosted headscale v0.29.5 control server, published by Erica Windisch on 2026-10-25 without coordinated disclosure. The report reproduces eleven findings (internal labels T1–T3, C1–C4, F-1–F-5) on unmodified, released software in a 2026-10-22 to 2026-10-24 testing window, across five components. Tailscale received the report on the morning of 2026-10-24 and the researcher published it two hours later; fixes shipped in Tailscale v1.104.4 (tagged 2026-10-27) with four security bulletins, TS-2026-014 through TS-2026-017. 1
What breaks
Findings 1–3 (High) are the core: Unix-socket forwarding (ssh -R/-L) in tailscaled’s embedded SSH server performs path checks and file operations as root, and races plus a missing privilege drop let an ordinary session replace, dial, or delete privileged resources. Demonstrated outcomes: root execution on target servers (a forwarded socket reaches root-only sockets such as dockerd’s), capture of device-enrollment keys, and arbitrary root-file deletion. The attacker requirement is one approved device plus one SSH policy rule permitting the connection. 2
The other classes:
- Finding 4 — the experimental conn25 app connector translates traffic to attacker-chosen destinations with no validation, and network ACLs are never consulted for the true destination: cloud-metadata credential theft, internal LANs, and in Kubernetes every cluster service. Tailscale’s response says Conn25 is pre-production and unreleased, the stable app connectors are unaffected, and the sensitive-destination blocking fix sat at open PR #22003 at the report’s 2026-10-28 snapshot.
- Findings 5–6 — a session-memory pin on tailscaled (bounded env churn and non-blocking window-change sends fixed it in v1.104.4), plus headscale’s unauthenticated memory/cache exhaustion and the DERP client’s unbounded read of a hostile relay’s response. The client-side bound shipped in v1.104.4; headscale-side admission control was still pending at the report’s snapshot.
- Findings 7–8 —
tailscale serve --tcpforwarding to a local unix socket lacked the guard the HTTP path had, exposing the agent’s local admin API to remote peers, and a TOCTOU race in per-mount authorization let a minority of requests bypass application authz. Both fixed in v1.104.4 (refusal at config time and per dial; openat2 inode pinning plus rechecks). - Findings 9–11 — the Funnel attribute check is enforced CLI-side only (Tailscale treats bypass as working-as-designed behind local admin access; status open),
TS_SERVE_ALLOW_ALL_INTERFACESis a documented opt-in knob, and header-authorization patterns across differing serve mounts bleed capabilities (fixed). 3
Tailscale’s own write-up classifies five Serve/Funnel findings as three bugs fixed in v1.104.4 and two as-designed behaviors. 4
The privilege model underneath
The researchers’ framing: tailscaled is a single highly-privileged process that replaces daemons like OpenSSH, which use privilege separation, and the mesh converts one ordinary foothold into fleet-wide privileged access at machine speed because inter-device paths are granted by policy that assumes trusted endpoints while the agent’s privileged operations are reachable from unprivileged sessions. Tailscale’s framing agrees on the mechanism: SSH servers need elevated privileges to start sessions as different Unix users, the challenge is keeping those privileges out of the connected user’s session, and the flaws concerned permission enforcement after a connection was authorized rather than the identity and policy checks that decide who connects. 5 6
On wormability the two accounts frame the same lab result differently. The report measured automated spread to every device the policy permits — no passwords, no stolen keys, under a second per hop — bounded by per-pair access grants (the single control that stopped it) and by TPM/Secure-Enclave-bound device credentials, which prevent identity theft from persisting. Tailscale objects to the name: the findings are not self-replicating malware, they are lateral movement limited to connections a tailnet policy file already allows. 7 8
The enrollment-key capture finding closes the loop demonstrated in the specification-gaming-openai-hf-incident: there, a stolen mesh-VPN auth key gave an agent “official-looking” network presence; here, root on one target yields the keys that enroll new machines, which in default (Tailnet-Lock-disabled) configurations join as legitimate tagged servers with routes auto-approved. Containment follows from the same key-material fact: delete the device at the control plane, because reimaging the host does not revoke a copied node-identity state file — stolen keys stay valid until deletion or expiry. 9
Remediation
In the report’s order of effect:
- Rewrite Tailscale SSH policy as per-pair grants — never identity-wide or tag-wide accept rules, never privileged target accounts. On headscale, treat every SSH grant as root-equivalent: forwarding v0.29.5 cannot be disabled and is granted unconditionally on every accepted session.
- On SaaS, set per-action forwarding flags to denied unless documented (or
TS_SSH_DISABLE_FORWARDING=1on the service); update tailscaled to v1.104.4 or later. Restricting SSH to non-privileged accounts is defense-in-depth only — the findings operate from fully unprivileged accounts. - Restrict app-connector entitlements and enforce destination allowlists on connector hosts (netfilter) or default-deny egress NetworkPolicy in Kubernetes.
- Node-key expiry on server fleets; TPM/Secure-Enclave-bound agent state; security telemetry kept off the compromised server’s reach; self-hosted headscale behind memory limits, restart supervision, and registration-rate throttling.
Check mode (time-based access grants) needs care: the lab rode a fixed-threshold detector (11 s against a 20 s rule) undetected, so privileged rules want checkPeriod of minutes or always, IdP step-up rather than session reuse, and never check mode as a forwarding control — the forwarding flags do that job. 10
Disclosure dynamics
The report shipped without coordinated disclosure — delivered 2026-10-24 morning, published two hours later — while Tailscale was already investigating concerns circulating since Friday 2026-10-23. Tailscale declined to recommend disabling Tailscale SSH outright (Mike Shaver, VP of Engineering, on Reddit), published an investigation update on 2026-10-26 targeting a same-day patched release, shipped v1.104.4 on 2026-10-27, and published the findings-and-fixes write-up on 2026-10-28. The researchers’ note adds a design critique: the product removed layers of authentication and privilege separation while marketing security as its design purpose. 11 12
Related
- specification-gaming-openai-hf-incident — the earlier case where a stolen Tailscale auth key produced persistent, official-looking network presence
- hermes-webui — the WebUI access path runs over Tailscale and SSH; the per-pair-grant and forwarding-flag guidance applies directly
- php2shell — the report’s foothold list (exploited web app, malicious build dependency, phishing implant, stolen credentials) starts with exactly the exposed-PHP class this page covers
Sources
- Cyberdione Labs (Erica Windisch) 2026 — Tailworm
- 2026 — Tailscale SSH: Findings and fixes
- Sergiu Gatlan 2026 — Tailscale warns of SSH flaws allowing root privilege escalation