Tailscale 刚刚在官方安全公告里承认,自家 SSH 功能曾经允许任何普通用户,只要把用户名改成 -i,就能在 Linux 主机上直接拿到 root 交互式会话——完全绕过管理员配置的 ACL 限制。这个漏洞编号 TS-2026-009,已经在 1.98.9 版本修复,官方发布日期是 2026 年 7 月 14 日。公告措辞很平淡,写的是"insecure argument handling"(不安全的参数处理),但拆开技术细节看,这是一次教科书级的权限提升。

-i 是怎么变成 root 的

Tailscale SSH 在 Linux 上查用户信息时,会把用户名直接拼进 getent passwd <username> 这条命令去执行。问题在于,getent 是一个命令行工具,它认识以 - 开头的字符串是"选项"而不是"参数"。当用户名是 -i 时,getent 会把它解释成 --no-idn 选项——结果不是查一个叫 -i 的用户,而是打印出整个 passwd 文件,从第一行 root 开始。Tailscale 拿到这个输出后,直接为用户开了一个 root 会话。

这类漏洞在安全圈有个专门名字,叫命令行参数注入(argument injection)。它的成因很老套:外部可控字符串被直接拼进子进程的命令行,程序没有用 -- 把"选项区"和"参数区"隔开。git、tar、rsync 的封装代码历史上都栽过同样的跟头。Tailscale 这次的修复方式也很标准——拒绝以 - 开头的用户名,并在 getent 支持的情况下改用 getent passwd -- <username>,用 -- 明确告诉程序"后面全是参数,不是选项"。

漏洞链路:一个用户名如何变成root会话 用户名 -i 拼进命令行 getent passwd -i 被解释为选项 --no-idn 吐出整个 passwd 文件 root 会话 ACL 被绕过 修复方式 拒绝以 - 开头的用户名 + getent 命令用 -- 分隔选项与参数 修复版本:Tailscale 1.98.9(2026-07-14 发布)

不是一次疏忽,是同一批四个洞

真正值得警惕的是,这次公告里一共列了四个漏洞,编号 TS-2026-006 到 009,全部在 1.98.9 里一起修复。其中三个都和"绕过 root 限制"直接相关:006 是用数字 UID 0 寻址绕过 autogroup:nonroot,009 是用户名前导短横线绕过同样的限制,008 则是 Serve/Funnel 组件的路径遍历导致 CPU 被无限占用的拒绝服务。006 和 009 的手法不同,但打的是同一堵墙——Tailscale 用 ACL 阻止普通用户以 root 身份登录,靠的正是"用户名/UID 解析"这一层的正确性。

这层解析出了两次不同方向的漏洞,说明问题可能不在某一行代码,而在这层设计本身没有把"合法用户身份"和"任意字符串"严格区分开。

零信任的边界只有身份解析这一层厚
  • 风险.依赖 autogroup:nonroot 做权限隔离的团队,在升级前,任何拿到 Tailscale SSH 访问权的账号理论上都能自己开出 root 会话。

无 CVE 编号,合规扫描可能漏判

检索目前没有查到 TS-2026-009 对应的公开 CVE 编号,只有 Tailscale 内部的追踪号。这意味着依赖 CVE 数据库做资产扫描或合规审计的企业,很可能不会在常规流程里命中这个漏洞,除非专门去看 Tailscale 官方公告页。这是原文公告本身没有提醒、但对运维团队有实际操作影响的一点。

另一个细节是,TS-2026-008 和 TS-2026-009 的报告者一栏里,都出现了 Anthropic 和安全审计公司 Ada Logics 的名字。两个技术路径完全不同的漏洞由同一组织连续报告,更像是一次系统性的代码审计工程,而不是零散的外部提交——但这背后是人工审计还是引入了 AI 辅助的代码扫描流程,官方公告没有说明,目前只能看到结果,看不到过程。


对使用 Tailscale SSH 托管生产环境跳板机的团队来说,升级到 1.98.9 是唯一的止损动作,官方给出的说法是"如果你使用 Tailscale SSH,升级即可,没有其他缓解措施"。更长期的问题是,身份解析这层代码接下来要不要做一次架构级别的重新审视——毕竟同一堵墙已经被绕过两次了。