同じClaude Codeの拡張機能でも、改ざん が確認されたのはCursorのマーケットプレイスで配られた2.1.313です。npm とOpen VSX、Microsoft のマーケットプレイスの公開記録に、この版はありません。
Cursorの告知によると、配布は太平洋時間の10月29日午前2時27分ごろから午後1時35分ごろまで。日本時間に直すと、29日18時27分ごろから30日5時35分ごろまでの約11時間で、影響は最大5,000人です。
厄介なのは、受け取ってしまった端末でしょう。読み込まれるだけで動き、拡張機能を消しても、攻撃者のSSH 鍵と接続をくり返すスクリプトが残ります。
影響するのはCursorで受け取った端末
「Claude Codeを使っている」だけでは対象になりません。配布先ごとの公開記録を10月30日に引いてみると、次のとおりでした。
配布先
2.1.313の記録
本物の2.1.312(日本時間)
本物の2.1.314(日本時間)
Cursorのマーケットプレイス
改ざん版を配布(Cursorの告知)
告知に記載なし
告知に記載なし
npm
なし
28日3時36分
30日9時12分
Open VSX
なし(APIは404)
28日5時26分〜27分
30日10時7分〜9分
Microsoftのマーケットプレイス
なし
28日5時36分〜41分
30日10時16分〜20分
2.1.312の次の番号なので、自動更新の端末には新しい版に見えたはずです。
Cursorの説明では、この版はAnthropicが開発したものではなく、ほかの版や公式の配布に影響した証拠も無いそうです。改ざん版を取り除いたあとはマーケットプレイス全体を止め、アクセスを監査して鍵を入れ替え、作り直してから再開しました。ほかの拡張機能に改ざんは無かったともいいます。
配布先ごとの時刻と、端末に残る痕跡を1枚にまとめた図 作成: 編集部 / 出典: 作成: 情シスの相棒編集部 / 出典: Cursor、Phorion、npm、Open VSX、Microsoft
Cursor以外の配布先は急がなくてよさそう
報道を追うと、出どころの説明は少し混ざったままです。OpenSourceMalwareは最初にOpen VSXと報告し、Socketによると共同創業者のLinkedInの投稿はnpmとMicrosoftを挙げていました。その後、Cursorの連絡を受けて記事を「Open VSXではない」と直しました。Help Net Securityは本文にOpen VSXと残しつつ、同じ記事の追記でManifold SecurityのAx Sharma氏の否定を載せました。Phorionの助言にも、npmとVS Codeの2.1.313を取り下げたとの記述があります。
混ざるのも無理はありません。Cursorの手引きによると、Cursorはサードパーティの拡張機能にOpen VSXを使いながら、検索とダウンロードは自社の中継を通し、Open VSXをそのまま通してはいないといいます。Open VSXの画面が正常でも、Cursorの利用者に届く物まで同じとは言えないわけです。
裏づけの強さは、配布先ごとに違います。いちばん強いのはOpen VSXで、Socketによると変更の記録は削除後も残る作りです。10月27日以降の3,392件に2.1.313の公開も削除も無く、同じ期間に公開して消された他の拡張機能の42版は両方の記録が残っていました。npmも公開時刻の記録に2.1.313がありませんが、Socketは絶対の保証ではないと断っています。Microsoftで確かめられるのは、今の一覧に無いことと、Socketの収集に掛からなかったことまでです。
OpenSourceMalwareも修正後の記事で、npmとOpen VSX、Microsoftの配布物は悪意のあるものではないと書きました。これらを合わせて編集部は、VS CodeとVSCodium、npm版の利用者は今のところ急がなくてよいとみています。もっとも、番号の飛び自体は事故の証拠になりません。npmでは2.1.250以降だけで、2.1.313を含めて10個の番号が欠けています。
更新された端末は、版の一覧で見分けられない
cursor --list-extensions --show-versionsで2.1.313が出れば、受け取った証拠です。ただ、本物の2.1.314に上がった端末には2.1.314しか出ません。
それでも攻撃者の鍵はauthorized_keysに残ります。そこで見るのは版ではなく鍵です。Cursorの告知にある確認のコマンドは、macOSならこの1行でした。
grep -qs svc-telemetry ~/.ssh/authorized_keys && echo "svc-telemetry key found" || echo "No key found; machine not impacted"
Windowsでは、PowerShellでこの2行を実行します。administrators_authorized_keysを読むには権限が要るので、管理者のPowerShellが確実です。
$files = "$HOME\.ssh\authorized_keys", "C:\ProgramData\ssh\administrators_authorized_keys" | Where-Object { Test-Path $_ }
if ($files -and (Select-String svc-telemetry $files)) { "svc-telemetry key found" } else { "No key found; machine not impacted" }
気をつけたいのは、実行するユーザーです。~と$HOMEは実行したユーザーのホームを指します。MDMやEDRからrootやSYSTEMで流すと、利用者の鍵を見ないまま「machine not impacted」と出かねません。
管理ツールから流すなら、全ユーザーを回す形にします。次の1つ目はmacOS用で、Linuxでは/Users/*を/home/* /rootに替えます。鍵の本体は、Cursorの除去スクリプトに載っている文字列です。
for d in /Users/*; do grep -qsF -e svc-telemetry -e AAAAC3NzaC1lZDI1NTE5AAAAIDdvylCEJ/k2TpezcTfedrkHyFSK9IZ3vmP6vhY4Ss0P "$d/.ssh/authorized_keys" && echo "$d: found"; done
Get-ChildItem C:\Users\*\.ssh\authorized_keys, C:\ProgramData\ssh\administrators_authorized_keys -Force -ErrorAction SilentlyContinue | Select-String -SimpleMatch -List -Pattern svc-telemetry, 'AAAAC3NzaC1lZDI1NTE5AAAAIDdvylCEJ/k2TpezcTfedrkHyFSK9IZ3vmP6vhY4Ss0P'
この2つはCursorの告知に無く、編集部が用意したものです。ループはLinuxで試しましたが、macOSとWindowsでは試していません。数台で動きを確かめてから広げてください。当たりが無いと終了コードが0以外になることがあるので、判定は出力で見ます。
痕跡は鍵のほかにもあり、OSごとの一覧を上の図の下段に載せました。OSの部品に似た名前なので、名前だけで判断しないほうが安全です。macOSのcom.apple.sysmondは~/Library/LaunchAgentsの下にあるものが対象で、WindowsのSysMonはMicrosoftの監視ツールと紛らわしいタスク名です。実行内容が.config\smt.cmdかどうかで見分けます。
古い版のフォルダーが残っていれば、中身でも判定できます。Cursorの除去スクリプトも、版番号ではなく中身で判定します。次の1つ目はmacOS用で、Linuxでは/Users/*を/home/*に替え、/rootも見ます。2つ目はWindows用です。ファイルが出れば受け取った証拠で、公式の2.1.312にこの文字列が無いことは確認しました。
grep -lF svc-telemetry /Users/*/.[!.]*/extensions/anthropic.claude-code-*/extension.js 2>/dev/null
Get-ChildItem C:\Users\*\.*\extensions\anthropic.claude-code-*\extension.js -Force -ErrorAction SilentlyContinue | Select-String -SimpleMatch -List svc-telemetry | Select-Object Path
通信のログも見ておきます。プロキシやファイアウォールで134[.]209[.]82[.]225への22番と8099番を探せば、誰かが鍵を消したあとでも手がかりになります。
Linuxの確認手順は告知に無い
Cursorの告知が改ざん版のパッケージとして挙げたのはdarwin-arm64とwin32-x64の2種類で、確認の手順もmacOSとWindowsだけです。Linux版が配られたかは分かりません。ただ、Phorionが分析したコードにはLinux向けの処理も入っていました。~/.config/.smtと~/.config/.smtkを置き、crontabに@rebootの行を足すもので、くり返し動くと既存のcronの行を消すおそれもあるそうです。
Cursorはこうも書いています。
Additionally, turning on the local SSH service requires admin rights, which the malicious extension does not have on most macOS and Windows hosts.
出典: Cursor「Security notice - malicious version of Anthropic.claude-code (2.1.313) identified in the Cursor Extension Marketplace」
攻撃者のサーバーも止まったといいますから、SSHが止まっている端末については、落ち着いて読める説明です。もっとも、鍵と常駐の仕組みは残るので、Cursorもそれでも除去するよう求めています。
ただ、分かれ目は端末の種類ではなく、SSHが動いていて、相手から届くかどうかです。
Remote Loginを有効にしたMacやOpenSSH Serverを入れたWindowsは、この説明に頼れません。Phorionも、macOSの不具合について、頼れる防御ではないと釘を刺しています。Linuxの開発サーバーならなおさらで、改ざん版が動いていれば、鍵に加えて公開IPとユーザー名も攻撃者に渡った可能性があります。SSHが届く場所からなら、トンネルが無くてもログインを試せるわけです。
では、Cursorでつないだサーバーで動いたのでしょうか。VS Codeの手引きではworkspace型の拡張機能はリモート側で動くとされます。ただ、公式の2.1.312のpackage.jsonには動く場所を決めるextensionKindの指定が無く、CursorのRemote SSHでどちらになるかは言い切れません。
それでも確認は数行で済みます。リモート接続で使っていたサーバーがあれば、上のループのLinux版に加えて、次もrootで流しておきたいところです。cronの行が消えていないかも、控えと比べます。
for d in /home/* /root; do u=$(basename "$d"); crontab -u "$u" -l 2>/dev/null | grep -F '.config/.smt' && echo "$u: cron"; ls -a "$d"/.config/.smt* 2>/dev/null; done; ls -a /tmp/.stk_* 2>/dev/null
秘密の値を持ち出さず、入口を残す
今年の似た事故と並べると、今回の特徴が見えてきます。
Nx Console 18.95.0
OVHcloud CLI 0.11.0〜0.15.0
Claude Code拡張2.1.313
時期
5月18日
10月19日
10月29日
配布先
MicrosoftのマーケットプレイスとOpen VSX
GitHubのリリース
Cursorのマーケットプレイス
置かれた時間
約11分と約36分
1時間33分
約11時間
発表された数
導入28回とダウンロード41回、内部集計で約6,000回の起動
約250回
最大5,000人
主な動き
認証情報を広く集めて送信。常駐のバックドアも置く
ディスクの秘密の情報を盗む
鍵の登録とトンネル、常駐。秘密の値は送らない
入口
貢献者のトークンの窃取
開発者のGitHubアカウントの使用
告知に記載なし
数え方はそれぞれの発表のままで、大小は比べられません。Nxは実際の影響がかなり多い可能性も認めました。
違いは持ち去るものです。Nx ConsoleとOVHcloud CLIは秘密の情報そのものを狙いました。Nxも常駐のバックドアを置きましたが、今回の改ざん版は秘密の値を送りません。送るのはホスト名やユーザー名、Gitのメールアドレス、公開IP、作業フォルダーと、キーやトークンらしい環境変数の名前を最大40個です。
これを軽いと読むのは危ないでしょう。Phorionは、名前の一覧があれば、どの端末にどのクラウドの認証情報があるかが分かり、狙う端末の優先順位を付けられるとみています。Cursorも、集めた情報が限られていても、バックドア経由であとから認証情報を取られた可能性は消せないという立場です。
まだ分からないことも残ります。改ざん版がマーケットプレイスに入った経路と、攻撃者がトンネルで何をしたかです。Anthropic自身の説明は、10月30日夜の時点で、検索した範囲では見つかりませんでした。同社の変更履歴は2.1.312の次が2.1.314で、理由の記載はありません。
今日のうちに確認する手順
Cursorを使っていない会社は、この節を飛ばしてかまいません。使っている会社は、次の順で進めます。
MDMやEDR、ソフトウェア台帳で、Cursorの入った端末を一覧にする。
開発部門に、台帳の外で入れたCursorが無いかを聞く。
一覧の端末と、Cursorのリモート接続先のサーバーで、鍵と図の下段のファイルを確認する。
プロキシとファイアウォールのログで、上の宛先への通信を探す。
同じ宛先の22番と8099番を、ファイアウォールで遮断する。
何か見つかった端末を、ネットワークから切り離す。サーバーは管理用の経路を残す。
消す前に、該当のファイルと実行中のプロセス、SSHのログを控える。
SSHのログで、鍵の指紋SHA256:0Z6R+DF64Do2nwQic8a7kkfDLNNk4IiK+2U2Rci4htkのログインを探す。送信元が127.0.0.1か::1ならトンネル経由。
除去スクリプトを実行し、再構築するかを決める。
別の信頼できる端末から、その端末で使えた認証情報とセッションを入れ替える。
8番で見つかれば、入られたとみて、再構築を選ぶのが無難でしょう。
除去スクリプトはCursorの告知に、macOS用のremediate-macos.shとWindows用のremediate-windows.ps1が載っています。切り離すと取りに行けないので、別の端末で先に用意しておきます。macOSは影響を受けたユーザーごとに、rootではなく本人で実行。Windowsは全部のエディターを閉じ、管理者のPowerShellで動かします。何か残ると終了コードは1です。何かを消して残りが無かったときに、22番で待ち受けるものがあれば、出力に「the tunnel exposed it」と出ます。Windowsのスクリプトはadministrators_authorized_keysを直さないので、そこで見つかった鍵は手で消します。
Linux用のスクリプトはありません。Phorionの手順に沿うなら、接続をくり返すループとトンネルを止めてから、@rebootの行と.smt、.smtk、/tmp/.stk_*を消します。Cursorのスクリプトの注記によると、鍵は本物の鍵と同じ行に続いて書かれることがあります。行ごと消さず、鍵の文字列だけを取り除くのが安全です。
連絡を待っていると遅れるかもしれません。Cursorは影響を受けた利用者へ直接知らせるとしていて、会社の管理者に届くとは書いていないからです。社員が個人で契約したCursorなら、なおさら情シスには届きにくいでしょう。「Cursorから連絡が来たら転送してほしい」と一言流しておくと、取りこぼしが減ります。
次の11時間をやり過ごす設定
Cursorのチーム設定に「Marketplace Install Cooldown」があります。公開から指定の時間が過ぎるまで、拡張機能の導入と更新を待たせるもので、Team settingsのSecurity & automationで管理者が決めます。個人の設定ならextensions.installCooldownHoursです。
既定は0、つまり無効。12時間にしてあれば、公開時刻が正しく付いていたかぎり、約11時間の配布は受け取らずに済んだ計算です。入り込んだ経路が分からないので、改ざん版にどの時刻が付いていたかまでは言えません。Enterpriseなら、Open VSXの署名を確認するRequire Extension Signature Verificationもありますが、今回効いたかは不明です。
もちろん、緊急の修正も同じ時間だけ遅れます。それでも編集部は、開発部門と話して24時間から始める価値があると考えています。
許可リストのextensions.allowedは、書き方で効き目が変わります。発行者の名前でも拡張機能のIDでも、今回の改ざん版は通っていたはずです。版を固定すれば新しい番号は止まりますが、同じ番号の中身を差し替えられると防げませんし、更新のたびに一覧を直す手間もかかります。同じ設定はVS Code 1.96以降にもあります。
監視するなら振る舞いです。Sharma氏は、発行者が本物なら名前の確認は役に立たず、コーディング用の拡張機能がSSH鍵を置いたら数秒で気づけるようにすべきだと述べました。Phorionも、エディターのプロセスがauthorized_keysに書き込む動きを監視するよう勧めます。どちらも検知の製品を扱う会社の発言なので、その点は割り引いて読みます。Phorionによると、プロセスの起動を見るだけのルールでは捕まらず、ファイルの書き込みの記録が要るとのこと。EDRがそこまで取れているなら、ルールに足しておくと、次に別の入口から来たときの手がかりになるでしょう。
もう1つ、台帳の話を。Cursorの手引きには、同じpublisher.extensionのIDでも、配布先によって別の発行者や中身を指すことがあると書かれています。拡張機能の台帳をお持ちなら、名前と版の隣に「どのエディターで、どの配布先から」の列を足しておくと、次に同じ話が出たときの答えが早くなるはずです。