Threat Overview
Tailscale released 1.104.4 to address four October 26 bulletins. TS-2026-014 concerns privileged Unix socket forwarding by Tailscale SSH; an authorized SSH peer permitted to forward sockets could reach root-only Docker or tailscaled local API sockets. TS-2026-015 allows an authenticated SSH peer to exhaust tailscaled memory. TS-2026-016 concerns Tailscale Serve Unix socket backend handling; TS-2026-017 involves HTTP/2 shared context and capability headers across mounts. The issue is a post-foothold access escalation and lateral movement risk, not an unauthenticated Internet-facing exploit.
References
Tailscale security bulletins — October 26, 2026
Tailscale investigation update
The Hacker News — October 28, 2026
Impacted Systems
Tailscale SSH server on Linux and the open-source macOS build, when SSH and local/remote forwarding are allowed; Serve deployments with Unix socket backends; Serve TLS with at least two mounts with different capability requirements. Fixed in Tailscale 1.104.4. The oldest affected release is not identified in the vendor bulletins. An attacker must control an authorized tailnet peer or hold permitted SSH access. Windows is not described as running the affected SSH server.
Why this matters
A single compromised, authorized peer may be able to reach root-only Unix sockets on another server if SSH policy grants forwarding. The flaw can undermine local privilege boundaries without an Internet-exposed SSH port.
Exploitation Status
Tailscale confirmed the flaws and issued patches; Erica Windisch demonstrated privileged socket access in a lab. No in-the-wild exploitation has been confirmed. Tailscale disputes the description of the chain as an autonomous worm and emphasizes policy restrictions still apply.
What this hunt looks for
Tailscale SSH forwarding and privileged-socket references, tailscaled OOM events, privileged commands after SSH access, new daemon egress, Serve configuration changes, and host configuration modifications.
Required logs
Syslog from Linux/macOS hosts and Defender DeviceProcessEvents, DeviceNetworkEvents, DeviceFileEvents where those sources are ingested into Microsoft Sentinel. Control-plane audit logs and Unix socket operations are not assumed to be visible.
Hunt 01 — Tailscale SSH forwarding and privileged socket references
Syslog
| where TimeGenerated > ago(30d)
| extend M=tolower(SyslogMessage)
| where M contains 'tailscale' or M contains 'tailscaled'
| where M contains 'forward' or M contains 'streamlocal' or M contains 'docker.sock' or M contains 'localapi'
| project TimeGenerated, Computer, ProcessName, SyslogMessage
| order by TimeGenerated desc
Hunt 02 — Tailscaled memory exhaustion and kernel OOM
Syslog
| where TimeGenerated > ago(30d)
| extend M=tolower(SyslogMessage)
| where (M contains 'tailscaled' and (M contains 'out of memory' or M contains 'oom' or M contains 'killed process')) or (M contains 'oom-killer' and M contains 'tailscale')
| project TimeGenerated, Computer, ProcessName, SyslogMessage
| order by TimeGenerated desc
Hunt 03 — Tailscale SSH session followed by privileged tools
DeviceProcessEvents
| extend EventTime=coalesce(todatetime(column_ifexists('TimeGenerated',datetime(null))),todatetime(column_ifexists('Timestamp',datetime(null))))
| where EventTime > ago(30d)
| extend Parent=tolower(InitiatingProcessFileName), Cmd=tolower(ProcessCommandLine)
| where Parent contains 'tailscale' or Parent contains 'ssh' or Cmd contains 'docker.sock' or Cmd contains 'tailscaled.sock'
| where FileName in~ ('docker','docker.exe','sudo','su','sh','bash','curl','socat','nc','ncat','python3') or Cmd contains '--unix-socket'
| project EventTime, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by EventTime desc
Hunt 04 — New tailscaled external destination
let old=DeviceNetworkEvents
| extend EventTime=coalesce(todatetime(column_ifexists('TimeGenerated',datetime(null))),todatetime(column_ifexists('Timestamp',datetime(null))))
| where EventTime between (ago(30d)..ago(2d)) and InitiatingProcessFileName =~ 'tailscaled'
| summarize by DeviceName, RemoteIP;
DeviceNetworkEvents
| extend EventTime=coalesce(todatetime(column_ifexists('TimeGenerated',datetime(null))),todatetime(column_ifexists('Timestamp',datetime(null))))
| where EventTime > ago(2d) and InitiatingProcessFileName =~ 'tailscaled'
| where isnotempty(RemoteIP) and not(ipv4_is_private(RemoteIP))
| join kind=leftanti old on DeviceName, RemoteIP
| project EventTime, DeviceName, RemoteIP, RemotePort, RemoteUrl, InitiatingProcessCommandLine
| order by EventTime desc
Hunt 05 — Tailscale Serve and SSH configuration changes
DeviceProcessEvents
| extend EventTime=coalesce(todatetime(column_ifexists('TimeGenerated',datetime(null))),todatetime(column_ifexists('Timestamp',datetime(null))))
| where EventTime > ago(30d)
| where FileName in~ ('tailscale','tailscale.exe','systemctl','sudo','bash','sh')
| extend Cmd=tolower(ProcessCommandLine)
| where Cmd contains 'tailscale serve' or Cmd contains 'tailscale ssh' or Cmd contains 'ts_ssh_disable_forwarding' or Cmd contains 'tailscaled.service'
| project EventTime, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName
| order by EventTime desc
Hunt 06 — Tailscale SSH session followed by root activity
let ssh=Syslog
| where TimeGenerated > ago(30d)
| where tolower(SyslogMessage) contains 'tailscale' and tolower(SyslogMessage) contains 'ssh'
| project Computer, SessionTime=TimeGenerated, SessionMessage=SyslogMessage;
let privilege=Syslog
| where TimeGenerated > ago(30d)
| where ProcessName in~ ('sudo','su','sshd') or tolower(SyslogMessage) contains 'session opened for user root'
| project Computer, PrivTime=TimeGenerated, PrivMessage=SyslogMessage;
ssh
| join kind=inner privilege on Computer
| where PrivTime between (SessionTime .. SessionTime + 10m)
| project Computer, SessionTime, PrivTime, SessionMessage, PrivMessage
| order by PrivTime desc
Hunt 07 — Tailscale configuration file edits
DeviceFileEvents
| extend EventTime=coalesce(todatetime(column_ifexists('TimeGenerated',datetime(null))),todatetime(column_ifexists('Timestamp',datetime(null))))
| where EventTime > ago(30d)
| extend P=tolower(FolderPath)
| where P contains '/etc/tailscale/' or P contains '/var/lib/tailscale/'
| where ActionType in~ ('FileCreated','FileModified','FileRenamed','FileDeleted')
| project EventTime, DeviceName, ActionType, FolderPath, FileName, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by EventTime desc
Detection Notes
The most meaningful correlations are Tailscale SSH session activity followed by unexpected privileged commands or evidence of access to root-only sockets. Most Unix socket operations are not visible in ordinary network events. DERP and peer churn cause expected tailscaled network changes. Syslog may not include forwarding detail; Linux endpoint file telemetry may be incomplete. No customer-specific workspace was queried; absent Sentinel matches would not establish absence of exploitation.