Skip to content

← Writing

engineering

Tailworm: 11 Findings in Tailscale and Headscale, and What to Do Before the Patch

· Jerwin Arnado · 7 min read ·

An independent security report called Tailworm lists 11 findings in Tailscale v1.104.2 and headscale v0.29.5. Most of them are in Tailscale SSH port and socket forwarding and in tailscale serve. Tailscale has merged fixes into main, but as of today, 28 October 2026, no numbered release includes them. If you use Tailscale SSH or serve, apply the mitigations below now. Don’t wait for the patch.

Status as of 28 October 2026: the latest client on Tailscale’s changelog is still v1.104.2 (21 October), and the security bulletins page has no entry for these findings yet. The report says a patched client was targeted for 27 October, subject to testing. I’ll update this post when it ships.

Tailscale is everywhere in homelabs and small teams, so this one deserves a careful read. Below is the short version for operators. I’ve left out the exploit details on purpose; the report has them if you need them.

What happened

  • Who wrote it: Erica Windisch of Cyberdione Labs. The researchers say they were not contracted or paid by anyone. Testing ran 22 to 24 October 2026.
  • What was tested: Tailscale v1.104.2 (Tailscale SSH, serve and funnel, the DERP relay client, and the experimental conn25 app connector), the gliderssh library it uses for SSH, and headscale v0.29.5, the self-hosted control server.
  • No CVEs or CVSS scores yet. The report rates its own findings, from “High” down to “configuration note”.
  • Upstream moved fast. Tailscale responded quickly. The report links merged pull requests for most of the SSH and serve findings.

Am I affected?

The headline findings need specific features turned on. A stock Tailscale install that only does WireGuard networking, without Tailscale SSH or serve, avoids most of the list.

You use… Findings Worst case (per the report)
Tailscale SSH with port or socket forwarding allowed 1, 2, 3 A user who is allowed to SSH in as an unprivileged account can get root-level effects through unix-socket forwarding
Tailscale SSH, any authenticated session 5 An SSH session can exhaust the memory of tailscaled, which runs as root
tailscale serve --tcp pointed at a unix socket 7, 8 An authorized peer can end up with write access to the local Tailscale API
serve over TLS with several mounts that have different app capabilities 11 A race lets one mount’s capabilities leak into another
conn25 app connector (experimental) 4 A user’s entitlement allows egress to destinations the policy doesn’t cover
Self-hosted headscale reachable from the internet 6 Unauthenticated requests can exhaust the control server’s memory
Funnel, or TS_SERVE_ALLOW_ALL_INTERFACES 9, 10 Edge cases in the threat model and configuration. Lower priority

If you’re on Tailscale’s hosted control plane and use neither SSH nor serve, you can relax a little. Update when the release lands.

What to do today

These come from the report’s interim guidance. They reduce risk; they are not full fixes.

If you use Tailscale SSH (findings 1–3, 5)

  • Assume an SSH grant is as good as root on that machine until you’ve patched. Plan your ACLs on that basis.
  • Narrow the SSH rules. Replace grants that cover a whole identity or tag with grants for specific user-and-host pairs. Never allow root or a passwordless-sudo account as a target.
  • Turn off forwarding where your control plane allows it. On Tailscale’s hosted service, set forwarding to denied in the SSH rules. On headscale v0.29.5 forwarding can’t be turned off, so every SSH grant there is effectively root.
  • Watch tailscaled memory (RSS). Finding 5 has no workaround on the Tailscale side, so fewer grants and monitoring are what you have.
  • Watch for signs of tampering: set auditd rules on unix-socket unlink, bind and chmod in /tmp, home directories and /run/user. Treat a socket with 0755 permissions where you expected 0600 as suspicious.
  • If you think a node is compromised, delete the device in the admin console. Reimaging the machine does not revoke a node key that someone has already copied. Also check where your auth keys have been issued and used.

If you use tailscale serve (findings 7, 8, 10, 11)

tailscale serve status
  • Run this on every node. Remove any --tcp forward that points at a unix socket, especially tailscaled’s own socket or anything else privileged.
  • Don’t set TS_SERVE_ALLOW_ALL_INTERFACES unless you really need it.
  • If you rely on header-based authorization across serve mounts with different capabilities, consider merging or separating those mounts until the fix for finding 11 ships.

If you self-host headscale (finding 6)

  • Keep the control server reachable from admin networks only, not from the whole internet.
  • Cap its memory and restart it automatically. With systemd, that’s MemoryMax= plus Restart=on-failure.
  • Rate-limit the registration endpoints at your reverse proxy.

If you run the conn25 app connector (finding 4)

  • Remove the connector capability from clients that don’t need it.
  • Enforce a destination allowlist on the connector host with netfilter. If the connector runs in Kubernetes, give its namespace a default-deny egress NetworkPolicy. The report includes a sample mitigation.

What’s fixed upstream

According to the report’s upstream section, updated 27 October:

Findings Fix State
1–3 (SSH forwarding) Forwarding redesigned so dial, bind and unlink run as the session user. Path checks are left to the kernel instead of string matching Merged to main
5 (gliderssh) Window-change events no longer block, and environment churn is bounded Merged
7 (serve to the local API) Refused when the config is set, and again on every connection Merged 27 Oct
8 (serve socket guard) Check repeated on every unix-socket connection PR open
11 (h2 race) Capabilities handled per request instead of from a shared connection context Merged
6 (relay client response body) Size of the response body read is bounded Merged 27 Oct
6 (headscale) Registration cache reworked Headscale PR pending
4, 9, 10 — No fix status given

Merged to main is not the same as shipped. Until the release, the mitigations above are the guidance for Tailscale ≤ v1.104.2 and headscale ≤ v0.29.6.

The bigger lesson

Plain WireGuard tunnelling came out of this mostly untouched. The trouble is in the convenience features layered on top: SSH that Tailscale handles for you, serve, funnel and app connectors. Each one is a root-owned daemon doing work on behalf of a less-privileged user, and that hand-off is where the classic bugs live, like the race between checking a path and using it, or forgetting to drop privileges.

Tailscale SSH and serve are worth the risk for me. But turning on a feature like that is more than flipping a switch. It’s an agreement to watch its advisories, keep its grants narrow, and patch the day the fix ships.

Sources: Tailworm report, Tailscale security bulletins, Tailscale changelog.