10月29日の夕方から翌朝にかけて、CursorでClaude Codeの拡張機能を使っていた人は、ふだんどおり作業していただけで攻撃者のSSH鍵を書き込まれた可能性があります。日本時間で10月29日18時27分から30日5時35分まで、Cursorの拡張マーケットプレイスがAnthropicの作っていない改ざん版「Anthropic.claude-code 2.1.313」を配っていました。
手元で調べて気づいたことがあります。npmに公開されているClaude Code本体には、2.1.313という版がそもそもありません。2.1.312の次は2.1.314です。正規の流れでは出るはずのない番号が、Cursor経由で届いていました。
対象になるのはCursorの利用者だけです。MicrosoftのVS CodeやターミナルのClaude Codeだけを使っている人は、今回の配布元とは別の経路を通っています。対象かどうかは、痕跡を探すスクリプトで1分あれば確かめられます。見つかったときに鍵を手で消してはいけない理由と、次の改ざんに備えた設定も、手元で確かめた結果と一緒に書きます。
配られたのはCursorのマーケットプレイスだけ。2.1.313は正規には存在しない番号
Cursorの10月29日のセキュリティ告知によると、改ざん版は米太平洋時間の2時27分から13時35分まで、約11時間公開されていました。影響を受けた利用者は最大5,000人で、Cursorは対象者へ個別に連絡するとしています。改ざん版は削除済みで、Cursorはマーケットプレイス全体をいったん止め、鍵を替えて作り直してから再開しました。
CursorはMicrosoftのVisual Studio Marketplaceではなく、自前のマーケットプレイスから拡張を配っています。手元のCursor 3.27.14の設定ファイル(product.json)を見ると、拡張の取得先はmarketplace.cursorapi.comでした。同じ名前の拡張でも、VS CodeとCursorでは届く経路が違います。
手元からも公開状況を確かめました。10月30日20時25分(日本時間)の時点で、Open VSXのClaude Code拡張は2.1.312と2.1.314だけを配っていて、2.1.313は「Extension not found」でした。npmのClaude Code本体も同じで、2.1.312の次は2.1.314です。
Claude Codeの公式ドキュメントには、拡張の版番号は同梱しているClaude Codeの版と同じだと書かれています。本体に存在しない2.1.313の拡張は、番号の時点で正規の流れから外れていました。
なお、改ざん版がOpen VSXにも載ったかどうかは解析した会社の間で見解が分かれています。StepSecurityはOpen VSXに公開されCursorがそれを中継したと書き、Socketの調査はOpen VSXに公開された形跡は見つからないとしています。現在のOpen VSXでは2.1.313は見つかりませんが、削除されたのか最初からなかったのかは、APIの応答だけでは区別できません。どうやって改ざん版が登録されたのかも公表されていません。
読み込んだだけで動く。ただし、ほとんどの環境でログインまでは失敗している
この改ざん版は、Cursorが拡張を読み込んだ時点で動きます。Claudeに話しかける必要はありません。Cursorの告知によると、やろうとしたことは4つです。
- ホスト名、ユーザー名、OS、作業フォルダ、Gitに設定したメールアドレス、公開IP、環境変数の名前を集めて攻撃者へ送る
- 攻撃者の公開鍵(名前はsvc-telemetry)を
~/.ssh/authorized_keysに追記する - パソコンのSSHサーバーを有効にし、攻撃者のサーバーへ逆向きのトンネルを張る
- macOSはLaunchAgent、Windowsはタスクに登録し、約60秒ごとにトンネルを張り直す
ここで大事なのは、Cursor自身が「管理者権限でCursorを起動したような非常にまれな場合を除き、悪性コードの誤りでSSHの段階は失敗する」と書いている点です。SSHサーバーを有効にするには管理者権限が必要で、多くのmacOSとWindowsではそこで止まり、攻撃者はトンネル経由でログインできなかったとしています。攻撃者のサーバーもすでに停止されています。
それでも、鍵の追記、常駐の仕組み、情報の送信は成功しています。私が気にしているのは環境変数の「名前」が送られた点です。値は送られていませんが、ANTHROPIC_API_KEYやGITHUB_TOKENのような名前が並べば、その端末に何の鍵があるかは相手に伝わります。
もうひとつ、もともとリモートログインを有効にしていたMacは話が別です。SSHサーバーを有効にする段階が要らないので、トンネルがつながった可能性を否定できません。Cursorの修復スクリプトも、痕跡があった端末で22番ポートが待ち受けていれば「トンネルがそれを外部に公開した」と表示する作りになっています。
確かめ方:拡張の版番号ではなく、残った痕跡を見る
今Cursorを開いて拡張が2.1.314になっていても、安心はできません。Cursorの修復スクリプトには「改ざん版は本物の版番号を保っているので、中身で照合する」というコメントがあります。それに、拡張を更新・削除しても、改ざん版が置いた常駐用のファイルは残ります。見るべきは版番号ではなく痕跡です。
macOS向けに、Cursorの告知に載っている痕跡をまとめて探すスクリプトを書きました。読み取るだけで、何も削除しません。check-cc313.shという名前で保存し、ターミナルでbash check-cc313.shと実行してください。zshに直接貼り付けると、該当ファイルがないときに「no matches found」で止まります。
#!/bin/bash
# 改ざん版Claude Code拡張2.1.313の痕跡を探す(macOS、読み取り専用。何も削除しない)
M=svc-telemetry
hit=0
for js in "$HOME"/.*/extensions/anthropic.claude-code-*/extension.js; do
[ -f "$js" ] || continue
if grep -qF -e "$M" -e 134.209.82.225 "$js"; then echo "改ざん版の拡張: ${js%/*}"; hit=1; fi
done
grep -qsF "$M" "$HOME/.ssh/authorized_keys" && { echo "攻撃者のSSH鍵: ~/.ssh/authorized_keys"; hit=1; }
for f in "$HOME/Library/LaunchAgents/com.apple.sysmond.plist" "$HOME/.config/.smt" "$HOME/.config/.smtk" \
"${TMPDIR:-/tmp}"/.stk_* /tmp/.stk_*; do
[ -e "$f" ] && { echo "不審なファイル: $f"; hit=1; }
done
pgrep -fl '\.stk_[0-9a-f]{10}|\.config/\.smt' && hit=1
[ $hit -eq 0 ] && echo "痕跡なし"
nc -z -G1 127.0.0.1 22 2>/dev/null && echo "参考: 22番ポートで待ち受け中(リモートログインが有効)"
exit $hit
このスクリプトの判定を確かめるため、テスト用のフォルダに偽の痕跡を作りました。攻撃者の接続先を含む偽のextension.js、正規の鍵と同じ行に攻撃者の鍵をつなげたauthorized_keys、偽のLaunchAgent、常駐用のファイル、トンネル用の鍵ファイルです。スクリプトはこの5か所をすべて見つけて終了コード1を返し、正規版を模した2.1.314のフォルダは無視しました。私のMac(macOS 26.4.1)で実行した結果は「痕跡なし」です。もともとClaude Code拡張を入れていないので、当然の結果ではあります。
実は最初に書いた版には見落としがありました。lsに2つの場所をまとめて渡したため、片方にファイルがないだけで「見つからない」扱いになり、トンネル用の鍵ファイル(.stk_で始まる)を見逃していました。上のスクリプトは1件ずつ確かめる形に直したものです。こうした確認用スクリプトは、偽の痕跡で一度ひっかかるかを試してから使うことをおすすめします。
Windowsは、Cursorの告知にあるPowerShellのコマンドで鍵の有無を確かめられます。%USERPROFILE%\.ssh\authorized_keysだけでなく、管理者用のC:\ProgramData\ssh\administrators_authorized_keysも見ています。
Linuxは注意が必要です。Cursorが公表した改ざん版のパッケージはmacOS(Apple Silicon)用とWindows用の2つで、Linux用の修復スクリプトはありません。一方でStepSecurityの解析は、常駐の手段としてcronの@rebootも挙げています。Linuxで2.1.313を入れた心当たりがあれば、grep -l svc-telemetry ~/.ssh/authorized_keysとcrontab -lの@reboot行を手で確かめてください。
見つかったら:Cursorのスクリプトで消し、authorized_keysを手で編集しない
痕跡があった場合の順番は、Cursorの告知とStepSecurityの推奨をまとめると次のとおりです。
- その端末をネットワークから外し、ほかの作業を止める
- Cursorの修復スクリプトを実行する。macOSはremediate-macos.shを影響を受けたユーザーで(sudoを付けずに)、Windowsはremediate-windows.ps1を管理者のPowerShellで動かす。何か残っていれば終了コードが0以外になる
- 22番ポートが待ち受けていた、またはトンネルがつながった形跡があるなら、掃除ではなく作り直しを検討する
- 別の安全な端末から、その端末で使えた認証情報を更新する。GitHubやGitLabのトークン、AnthropicやOpenAIのAPIキー、クラウドの鍵、SSH鍵、npmなどのレジストリのトークンが対象
手で直したくなる気持ちは分かりますが、authorized_keysをgrep -v svc-telemetryやsedで行ごと消すのはやめてください。Cursorの修復スクリプトのコメントによると、攻撃者の鍵は先頭に改行を付けずに追記されるため、既存の正規の鍵と同じ1行につながることがあります。私が作ったテスト用のファイルでgrep -vを試すと、残った行は0行でした。攻撃者の鍵と一緒に、自分の鍵まで消えます。Cursorのスクリプトは、攻撃者の鍵の文字列だけを取り除くように書かれています。
APIキーの止め方は、各社の画面で手順が違います。以前書いたOpenCodeのAPIキー流出で今やることに、OpenAI・Anthropic・Geminiの失効手順と、支出上限で止められる範囲をまとめています。
次の改ざんに備える:VS Codeにある「公開後しばらく待つ」設定が、Cursorにはない
私は、被害が広がった理由のひとつは、拡張の自動更新が既定でオンだったことだと見ています。Cursorを開いていただけで、新しい版が入ってくるからです。そこで、手元のCursorとVS Codeの本体から、拡張の自動更新まわりの設定を読み出して比べました。
| 確かめた項目 | Cursor 3.27.14 | VS Code 1.129.1 |
|---|---|---|
| 拡張の自動更新の既定 | オン | オン |
| 公開から自動更新までの待ち時間 | 設定がない | あり(既定2時間) |
| 拡張ごとに自動更新を切る | できる | できる |
| 版を指定して入れ直す | できる | できる |
VS Codeのextensions.autoUpdateDelayは、拡張の新しい版が公開されてから自動で入れるまでを、時間単位で待たせる設定です。VS Codeのドキュメントでは既定が12時間ですが、手元の1.129.1の既定は2時間でした。Cursorの本体には、この設定の定義自体が見当たりませんでした。
今回の公開時間で計算してみます。改ざん版は日本時間18時27分に公開され、翌5時35分に消されたので、11時間8分です。待ち時間が2時間なら、20時27分以降に自動更新した端末には届きます。12時間なら自動で入るのは翌6時27分以降になり、その前に削除が終わっています。設定の説明から出した計算で、実際に試したわけではありません。それでも、待ち時間が半日あれば今回の改ざん版は自動では入らなかったことになります。
Cursorでこの設定が使えない以上、私はClaude Code拡張の自動更新だけを切るのが現実的だと考えます。拡張の一覧でClaude Codeを右クリックし、メニューのAuto Update(自動更新)のチェックを外します。更新は週に一度など、自分で決めた日に手動で行います。
手動で更新する前には、同じ版がnpmにあるかを確かめると安心です。拡張の版はClaude Code本体の版と同じなので、npm view @anthropic-ai/claude-code@2.1.314 versionのように打ちます。私の環境では2.1.314は版番号が返り、2.1.313は「No match found」のエラーになりました。番号が一致しても中身が正しいとまでは言えませんが、今回の改ざん版はこの確認で引っかかりました。
ただし、自動更新を切ると、脆弱性の修正も自分で取りにいく必要があります。HTTP2Shellの件では、Claude Codeを2.1.308以上へ上げる必要がありました。手動にするなら、セキュリティの告知を見たらその日のうちに更新すると決めておくのが条件です。
もうひとつ知っておきたいのは、拡張を消しても戻ってくることです。公式ドキュメントによると、VS Codeの統合ターミナルでclaudeを起動すると、Claude Codeは拡張を自動で入れ直します。Cursorでも同じ動きになるかは確かめていません。拡張なしで使いたい場合は、/configのAuto-install IDE extensionを切るか、設定のautoInstallIdeExtensionをfalseにします。
今日やること
10月29日の夕方から30日の朝にCursorを開いていて、Claude Code拡張を入れていたなら、まず上のスクリプトかCursorの告知のコマンドで痕跡を確かめてください。数秒で終わります。痕跡がなければ、Claude Code拡張の自動更新を切っておけば今日の作業は終わりです。
痕跡が見つかったら、authorized_keysには触らず、Cursorのスクリプトで消してから別の端末で鍵を替えてください。今回の件で分かるのは、エディタの拡張がターミナルと同じ権限で動き、鍵の追記も常駐の登録もできてしまうことです。使っていない拡張は外し、残す拡張は更新のタイミングを自分で決める。私はこの2つを、Claude Codeに限らず全部の拡張に当てはめるつもりです。

コメント