Tailscaleの脆弱性レポート「Tailworm」11件の対処法|修正版が出るまでにやること

(更新: 2026年11月6日)

Tailscale の基本的な使い方は「自宅PCをTailscaleで繋ぐSSH接続チュートリアル」に、スマホから SSH する全体像は「モバイルSSH完全ガイド」にまとめています。この記事は、2026年10月に出た脆弱性レポートへの守る側の対処だけを扱います。

この記事の要点(30秒)

  • 2026年10月25日、研究者が Tailscale と headscale の問題 11件 をまとめたレポート「Tailworm」を公開した。Tailscale は翌26日に問題を認め、10月28日の 1.104.4 で修正した(headscale は 0.29.7)。全端末を 1.104.4 以上に更新する(2026年11月6日に確認)
  • いちばん重いのは Tailscale SSH。SSH を許可された端末が1台乗っ取られると、ほかのサーバーまで被害が広がりうる
  • 効き目が一番大きい対策は、SSH を許可するルールを「この端末からこの端末へ」の組み合わせ単位に絞ること。使わない端末では Tailscale SSH を止める
  • serve・App Connector・headscale は、使っている人だけ対処すればいい
  • 全員共通でやるのは、Tailnet Lock・キーの期限・侵害時は管理画面で端末を削除、の3つ

この記事では攻撃の手順には触れません。「自分は対象か」「何をすればいいか」に絞って書きます。


何が起きたのか

2026年10月25日、Cyberdione Labs の Erica Windisch 氏が「Tailworm」というレポートを公開しました。対象は Tailscale 1.104.2 と headscale 0.29.5 で、10月22日から24日にかけて検証環境で再現を確かめた、と書かれています。速報記事では Cyber Security News の記事(英語)が詳しいです。

押さえておきたい前提が3つあります。

  1. Tailscale は認めて修正した。公開時点(10月26日)では公式の告知も修正版もなかったが、その後 1.104.4 で直った。詳しくは次の節に書きます
  2. 結果は検証環境でのもの。実際に悪用された被害は報告されていない。深刻さには異論も出ている
  3. それでも設定で今すぐ絞れる部分が大きい。修正を待つあいだ、何もしない理由にはならない

ちなみに Tailscale SSH では、2026年7月にも別の問題(TS-2026-009)が 1.98.9 で直っています。こちらは修正済みなので、古い端末が残っていないかだけ見ておけば大丈夫です。

修正版の状況と更新の確かめ方(11月6日時点)

公開から10日たったので、Tailscale と headscale の公式情報を確かめ直しました(2026年11月6日)。

日付出たもの中身
10月26日Security Bulletins TS-2026-014〜017Tailscale SSH の Unix ソケット転送(F1・F2・F3)、SSH のメモリ枯渇(F5)、serve の Unix ソケット転送先と HTTP/2 の権限ヘッダー(F7・F8 ほか)
10月28日Tailscale 1.104.4上の4件を修正。SSH の転送は root ではなくログインしたユーザーの権限で動くようになった
10月30日headscale 0.29.7headscale 側の指摘(F6)を修正。Tailscale 側の修正は入らないので、クライアントも 1.104.4 以上にする
11月2日Tailscale 1.104.5SSH・serve の安定性の修正。この時点の最新

CVE 番号はどれにも付いていません。Bulletin の番号(TS-2026-014 など)で追うことになります。

全部が直ったわけではありません。App Connector(F4)は、内部アドレスやメタデータへの踏み台になる部分だけ開発中のコードで塞がれていて、リリース版にはまだ入っていません(Tailworm のサイトの「Upstream response」節による)。App Connector を使っている人は、下の「App Connector(F4)」の対処を続けてください。

更新したかどうかの確かめ方

各端末で次を実行し、1行目が 1.104.4 以上なら修正済みです。Mac の GUI 版は「ぼくの環境で確かめてみた」に書いたアプリ内のパスで実行します。

tailscale version

headscale を運用している場合はサーバーで headscale version を実行し、0.29.7 以上か確かめます。

すぐに更新できない端末は、Bulletin が示す回避策として、tailscaled のサービスの環境変数に TS_SSH_DISABLE_FORWARDING=1 を入れると SSH の転送を止められます。headscale のリリースノートによると、古いクライアントでも効きます。

ぼくの常時起動の Linux サーバーで確かめると、tailscale version は 1.104.5、Tailscale SSH は無効(RunSSH: false)、tailscale lock status は「Tailnet Lock is ENABLED.」でした。記事を書いたときに「要対処」だった Tailnet Lock は有効になっていて、このサーバーは署名済みの端末としてふだんどおり使えています。

修正版が出ても、SSH ルールを組み合わせ単位に絞る・使わない機能を止める、の2つはそのまま続ける価値があります。今回の修正で塞がったのは見つかった穴で、「1台乗っ取られたら広がる」という構造は、ルールが広いままなら残るからです。

被害の広さを決めるのは「SSH ルールの広さ」

レポートでいちばん大事なのは、個々のバグより次の指摘だとぼくは思っています。

Tailscale SSH は、パスワードや鍵ではなく「どの端末からの接続か」だけで、SSH を通すかどうかを決めます。つまり「この端末は信用できる」という前提で動いている。その前提が崩れる(1台が乗っ取られる)と、ルールで許可されたすべての相手に被害が届きます。

SSH ルールの広さと影響範囲端末同士の SSH を全員から全サーバーへ許可していると1台の侵害が全サーバーに届くが、端末の組み合わせごとに許可すると届くのは許可した1台だけになる。広いルール(全員 → 全サーバー)組み合わせ単位のルール(1台 → 1台)拒否拒否許可乗っ取られた 1 台社内のどこかの端末乗っ取られた 1 台社内のどこかの端末サーバー Aサーバー Bサーバー Cサーバー Aサーバー Bサーバー Cルールが広いと、1 台の侵害が全サーバーに届く組み合わせごとに許可すると、届くのは 1 台だけ
図1: 守りの効き目を一番左右するのは、SSH を許可するルールの広さ

研究者の検証でも、広がりを止められた対策は組み合わせ単位の許可(per-pair grants)だけだったそうです。ほかの対策は「気づくのが早くなる」効果はあっても、広がり自体は止めなかった、と。

薬局で例えると、「スタッフ全員がどの金庫も開けられる」状態か、「麻薬金庫は麻薬管理者だけ」状態か、の違いです。前者だと、誰か1人の鍵が盗まれた時点で全部の金庫が危ない。管理薬剤師をやっていたころ、鍵の管理簿をつけるのは正直めんどくさかったけど、あれはこういう事態のためにあるんですよね。

根本の原因は「root のまま動く SSH サーバー」

もうひとつ知っておくと対策を選びやすくなるのが、設計の違いです。

ふつうの SSH サーバー(OpenSSH)は、ログインが終わるとすぐにそのユーザーの権限に落としてから作業します。だから一般ユーザーのセッションから、root 専用の仕組みには触れません。

Tailscale SSH は tailscaled という常駐プログラムの中に SSH サーバーが入っていて、これは root 権限で動いています。レポートによると、SSH の転送機能(ssh -L / ssh -R で Unix ソケットを扱うもの)を root のまま処理してしまうため、一般ユーザーのセッションから root 専用のソケットに届いてしまう、とのことです。

OpenSSH と Tailscale SSH の権限の違いOpenSSH はセッション用の子プロセスを一般ユーザーに降格してから root 専用ソケットに触るので拒否されるが、Tailscale SSH は root のままの tailscaled がソケットに触るためつながる。OpenSSHTailscale SSH拒否つながる一般ユーザーの SSH セッションssh -L / ssh -Rsshd(root)認証と監視だけセッション用の子プロセス一般ユーザーの uid に降格root 専用ソケット/run/docker.sock などtailscaled(root のまま)SSH サーバーを内蔵root 専用ソケット/run/docker.sock などDropbear は同じ種類の問題を 2025.89 で修正(CVE-2025-14282)
図2: 同じ「一般ユーザーのSSHセッション」でも、ソケットを触るのが誰の権限かが違う

同じ種類の問題は、別の SSH サーバー Dropbear でも CVE-2025-14282 として見つかっていて、2025.89 で「先にユーザー権限へ落とす」形で直っています。なので、Tailscale 側の修正もそれほど大きくはならないはず、というのが研究者の見立てです。

この違いから言えるのは、Tailscale SSH の許可は「root を渡すのとほぼ同じ」と考えて扱うのが安全、ということです。

11件の中身と、それぞれの対処

11件は5つの機能に分かれます。使っていない機能の節は読み飛ばしてOKです。

#機能中身(ざっくり)レポートの深刻度対象になる人
F1〜F3Tailscale SSH転送機能が root で動き、root 専用のソケットに触れるHighSSH で転送を許可している
F4App Connector(conn25)許可されたアプリ以外の宛先にも通れてしまうHigh実験機能の conn25 を使っている
F5Tailscale SSHセッションを使ってメモリを食いつぶせるHighSSH を許可している
F6headscale / DERP登録処理でメモリを枯渇させられる。悪意あるリレーで端末が落ちるMedium-Highheadscale を公開している
F7serveUnix ソケットへの TCP 転送で、管理用の窓口が外から使えるHighserve でソケットへ転送している
F8serve設定後にパスをすり替えると、ソケットのチェックを抜けられるMedium同上(書き込める場所のソケット)
F9FunnelFunnel の有効化チェックが手元の設定に頼っているMediumFunnel を使える端末
F10serveTS_SERVE_ALLOW_ALL_INTERFACES で Tailnet の外からも見える設定の注意この変数を設定している
F11serveヘッダーで権限を分けている場合、まれに別の権限が混ざるMedium〜Lowヘッダーで認可している

Tailscale SSH(F1・F2・F3・F5)

対象: Tailscale SSH を有効にした端末がある人。ここがいちばん重いです。

やること

  1. 使わない端末では止める。別の入り方(OpenSSH やコンソール)があることを先に確かめてから実行します。止めた瞬間に入れなくなる可能性があるので、順番が大事です
sudo tailscale set --ssh=false
  1. 残す端末は、ポリシーの ssh ルールを組み合わせ単位にする。autogroup:member やタグ全体を dst に並べるのをやめ、「この端末(またはこの人)から、このサーバーへ」と1組ずつ書きます
  2. root や、パスワードなしで sudo できるアカウントを users に入れない。ただしレポートの指摘は一般ユーザーのセッションから成立するので、これは補助的な対策です
  3. 転送を禁止する。レポートは「SaaS 版ではルールごとに転送を拒否できる」としています。ただ、ぼくが公式のポリシーファイルのリファレンスを確認した範囲(2026年10月26日)では、ssh ルールに書ける項目は action / src / dst / users / checkPeriod / acceptEnv / srcPosture だけで、転送を止める項目は見つかりませんでした。なので、転送を確実に止めたいなら Tailscale SSH をやめて、Tailnet 越しに OpenSSH を使うのが現実的だと思います。OpenSSH なら sshd_config に次の1行で転送をまとめて止められます
DisableForwarding yes

この場合はネットワークの ACL(grants)で、22番ポートへの通信も組み合わせ単位で許可してください。

F5(メモリの食いつぶし)だけは、Tailscale 側でできる回避策がレポートでも見つかっていません。上流のライブラリ(gliderlabs/ssh)の修正待ちです。SSH を許可する相手を絞ることが、そのまま F5 の影響を小さくします。

check モードを使っている人へ

action: "check"(接続前にブラウザで再認証させる設定)を、強い守りだと思って使っている人もいると思います。レポートはここにも注意を出しています。

  • check モードが確認するのはセッションを始めるときだけ。始まったセッションの中の転送は制限しない
  • SaaS 版では、1回の承認がほかの check 対象すべてに有効になる(期間は checkPeriod、既定は12時間)
  • 自分で開いた覚えのない認証の画面が出たら、それ自体をインシデントとして扱う

なので、大事なサーバー向けのルールは checkPeriod を数分か "always" にしておくのがおすすめです。

tailscale serve と Funnel(F7〜F11)

対象: tailscale serve や Funnel を使っている人。

#確認すること対処
F7tailscale serve status に、unix: で始まる転送先がないかあれば消す。特に tailscaled.sock を指しているものは必ず消す
F8Unix ソケットの転送先が、誰でも書き込めるディレクトリにないかlocalhost の TCP ポートに切り替えるか、root だけが書ける場所に置く
F9tailscale funnel status で、意図しない Funnel が有効になっていないか使わないなら止める。serve の設定を変えられる人(operator)を最小限にする
F10環境変数 TS_SERVE_ALLOW_ALL_INTERFACES を設定していないか必要がなければ外す(Kubernetes operator の実験的な機能が設定することがある)
F11serve の複数のパスで、Tailscale-App-Capabilities ヘッダーを使って権限を分けていないか権限の違うアプリは別のポートやホスト名に分ける(ぼくの判断。レポートの提案は Tailscale 側の修正)

ぼくが見た限り、serve を http://localhost:3000 のような TCP のローカルポートに向けているだけなら F7・F8 には当たりません。ぼくの使い方もこれでした。

App Connector(F4)

対象: 実験機能の conn25(新しい App Connector の仕組み)を使っている人。従来の App Connector だけなら対象外です。

レポートによると、アプリの利用を許可されたユーザーが、そのアプリ以外の宛先にもコネクタ経由で通れてしまいます。クラウドの認証情報が取れるメタデータサービスや、Kubernetes のクラスタ内のサービスまで届く、とのこと。

やること

  • 使っていない端末から、コネクタの権限を外す
  • コネクタのホストで、ファイアウォールで宛先を許可リストにする。特に 169.254.0.0/16(メタデータ)は無条件で止める
  • Kubernetes では、コネクタの namespace に「既定で外向き通信を拒否」する NetworkPolicy を入れる
  • 1台のコネクタ(同じ外向き IP)に複数のアプリを相乗りさせない

headscale(F6)

対象: Tailscale の代わりに headscale を自分で運用している人。

  • systemd の MemoryMax でメモリの上限を決め、落ちても自動で再起動するようにする
  • 登録の窓口の前にレート制限つきのリバースプロキシを置く
  • インターネットに丸出しにせず、管理用のネットワークや VPN からだけ届くようにする
  • headscale 0.29.5 では SSH の転送を止められないので、SSH の許可はすべて root を渡すのと同じとみなし、許可そのものを減らす
  • 端末が使うリレー(DERP)は、自分が管理しているか信頼できるものだけにする

全員共通でやること

ここまでの機能を使っていなくても、次の3つはやっておく価値があります。どれも「乗っ取られたあとに被害を長引かせない」ための対策です。

1. Tailnet Lock を有効にする

Tailnet Lock を有効にすると、信頼済みの端末が署名しない限り、新しい端末は参加できません。レポートでも、Lock が無効な初期設定だと被害が大きくなると書かれています。

2. キーの期限をつける

タグをつけた端末は、初期設定でキーの期限が無効になっています。サーバーにも期限をつけておけば、盗まれた鍵がいつまでも使える状態を避けられます。対応している端末なら、TPM や Secure Enclave に鍵を置く設定も有効です。

3. 侵害を疑ったら、管理画面で端末を削除する

ここは誤解しやすいところです。端末の鍵はファイルとして保存されているので、root を取られたらコピーされたと考える必要があります。OS を入れ直しても、コピーされた鍵は生きたまま。止められるのは管理画面からの削除(か期限切れ)だけです。

削除したら、その端末から使えた認証キーや資格情報も作り直します。Tailnet Lock の署名に使っていた端末なら、Lock の鍵も入れ替えます。最後に、ポリシーの変更履歴に覚えのない変更がないかも見ておきましょう。

ちなみに、Hugging Face の侵害でも、盗まれた Tailscale の認証情報で181台が登録されたと Tailscale が説明しています(こちらは脆弱性ではない)。コードの問題と同じくらい、鍵の扱いが大事ということですね。

検知の仕組みを入れられるなら

Linux のサーバーを多く抱えている組織なら、レポートが挙げている次の監視も検討してください。

  • auditd で、/tmp・ホーム・/run/user と tailscaled 自身のソケットの作成・削除・権限変更を記録する
  • 認証キーの発行と利用、見たことのない鍵での端末の参加を通知する
  • headscale のメモリ使用量と登録の遅延を監視する

ただし、検知は「気づくのが早くなる」だけで、広がる速さ自体は変えません。

対策の効き目を並べると

ここまでの対策を、効き目の大きい順に積み重ねるとこうなります。上の層で止めきれなかったものを、下の層が受け止める形です。

対策ごとに止められるものと残るもの乗っ取られた1台を起点に、6つの対策を上から順に重ねた図。各層が止めるものと、止めきれずに次の層へ渡る残りのリスクを並べている。端末の組ごとに SSH を許可する対策だけが、他の端末への広がりを止めた。起点:tailnet の1台が乗っ取られる対策(上から順に効く)止める残る → 次の層へ01端末の組ごとに SSH を許可組み合わせ単位で許可を絞る他の端末への広がり許可した1組の中ではroot 化できる02SSH の転送を禁止ソケット転送での root 化(F1〜F3)セッションでのメモリ枯渇(F5)headscale では禁止できない03出口を nftables で制限tailscaled の通信先を絞る-L の TCP 転送先:ループバック・メタデータ・LANUnix ソケットの操作はファイアウォールを通らない04Tailnet Lock・鍵の期限TPM / Secure Enclave で鍵を保護盗んだ鍵での偽端末の参加と居座り期限内の鍵は使える05検知ソケットの unlink / bind / chmod、rename の嵐、未知の鍵での参加気づくまでの時間広がる速さそのものは変わらない06管理画面から端末を削除コピーされた鍵の再利用—(再イメージだけでは鍵は失効しない)
図3: 対策ごとに「止められるもの」と「残るもの」

一番上の「組み合わせごとに許可」が、唯一広がりそのものを止める層です。ほかの層は、それをすり抜けたときの保険だと考えると優先順位がつけやすいです。

ぼくの環境で確かめてみた

記事を書く前に、自分の Tailnet を一通り点検しました。手元は Mac mini(Tailscale 1.102.4)が中心で、ほかに MacBook、Windows、iPhone、Android、Linux が数台つながっています。

まずつまずいたのが、Mac で tailscale コマンドが見つからないこと。App Store / GUI 版を入れている場合、CLI はアプリの中にあります。

/Applications/Tailscale.app/Contents/MacOS/Tailscale version

点検に使ったコマンドはこれだけです。どれも状態を表示するだけなので、安心して実行できます。

# この端末で Tailscale SSH と App Connector が有効か
tailscale debug prefs | jq '{RunSSH, AppConnector}'

# SSH のホスト鍵を公開している端末(Tailscale SSH が有効な端末の目安)
tailscale status --json | jq -r '.Peer[] | select((.sshHostKeys // []) | length > 0) | .HostName'

# serve と Funnel の設定
tailscale serve status
tailscale funnel status

# Tailnet Lock の状態
tailscale lock status

結果はこんな感じでした。

項目ぼくの環境判定
Mac mini の Tailscale SSH無効対象外
servelocalhost の TCP ポートに転送しているだけF7・F8 は対象外
Funnel・App Connectorどちらも使っていない対象外
Linux 2台の Tailscale SSH有効要対処
Tailnet Lock無効要対処

正直、Linux の2台で Tailscale SSH を有効にしていたことは完全に忘れていました。以前、開発用に立てたときにオンにして、そのまま。しかもぼくは Tailnet の管理者なのに、Tailnet Lock も有効にしていなかった。

「自分は大丈夫でしょ」と思っていたのに、ふたを開けたら2つ引っかかったわけです。点検してよかった…。2台はどちらもオフラインだったので、次に起動したときに tailscale set --ssh=false で止めて、Tailnet Lock を有効にする予定です。

自分の環境でやることを決める

最後に、ここまでの内容を判定フローにまとめておきます。上から順に答えていけば、自分がやることにたどり着きます。

自分の環境でやることを決めるフローTailscale SSH、serve の Unix ソケット転送、App Connector、headscale 運用の4つの質問に順に答え、当てはまれば対策(不要な SSH を止める、転送を消す、権限と宛先を絞る、headscale の上限と公開範囲を絞る)を行い、最後に全員共通の Tailnet Lock・キー期限・侵害時の端末削除にたどり着く流れ。いいえはいいいえはいいいえはいいいえはいTailscale SSH を有効にした端末がある?tailscale debug prefs → RunSSHserve で Unix ソケットに転送している?serve --tcp … unix:App Connector(conn25)を使っている?headscale を自分で運用している?不要な端末は止める残すなら組み合わせ単位+転送禁止tailscale set --ssh=falseその転送を消す(F7 / F8)権限を外す・宛先を許可リストで絞るK8s: default-deny egressメモリ上限・登録のレート制限・公開範囲を絞るMemoryMax全員共通Tailnet Lock・キーの期限・侵害時は管理画面で削除
図4: 自分の環境でやることを決めるフロー

評価が割れていることも書いておく

公平のために書いておくと、このレポートには「深刻さを大きく見せすぎだ」という声もあります。結果はあくまで研究者の検証環境のもので、実際の被害は報告されていません。また、ほとんどの項目は「すでに1台が乗っ取られている」ことが前提です。

ただ、ぼくの結論は変わりません。SSH ルールを組み合わせ単位にする、使わない機能を止める、Tailnet Lock を入れる。この3つは修正版が出たあとも続ける価値のある、基本の守りだからです。

Tailscale からの公式な情報は Security Bulletins に出ます。修正版(1.104.4)はもう出ているので、全端末を更新しましょう。Tailscale SSH 自体の仕様は公式ドキュメントにあります。

まとめ

  • Tailworm は Tailscale と headscale の問題11件をまとめたレポート。Tailscale 1.104.4・headscale 0.29.7 で修正された(App Connector は一部のみ)。全端末を更新する
  • いちばん重いのは Tailscale SSH。SSH の許可は root を渡すのと同じと考え、組み合わせ単位に絞る。使わない端末では止める
  • serve(Unix ソケットへの転送)・App Connector(conn25)・headscale は、使っている人だけ対処する
  • 全員共通で、Tailnet Lock・キーの期限・侵害時は管理画面で削除

Tailscale は、ぼくがスマホから自宅の PC に入って開発するのに欠かせない道具です(構築の手順は「TailscaleでClaude CodeにSSH接続する方法」に書きました)。便利な道具だからこそ、「つながる範囲」をときどき棚卸しするのが大事だなと改めて思いました。

続報が出たら、この記事も更新します。気になる方は X(@hagakun_yakuzai) をフォローしてもらえるとうれしいです🙌

急に朝晩が冷えてきましたね。サーバーの棚卸しついでに、衣替えもしないと…。

参考資料