この記事は後半です。前半は Qiita にあります: 管理者権限エラーが「SSHはオン」に化けた理由――Cursor版Claude Code拡張の空振りを追う
Off を待っていた判定が、エラー文に負けた
画像: socket.dev より
Phorion の分析で核心はかなりはっきりした。攻撃側は systemsetup -getremotelogin の結果に Off が含まれるときだけ、sudo -n systemsetup -setremotelogin on を実行する作りだった。ところが macOS では、標準ユーザーでこのコマンドを叩くと、設定値ではなく「管理者アクセスが必要」というエラー文が返る。しかも終了コードは 0 のままなので、見た目だけだと成功失敗の判定がさらにややこしい。
結果として、攻撃コードは「SSH がオフだから有効化する」という分岐に入れない。権限不足で状態確認できなかっただけなのに、文字列判定のせいで「オフではない」と解釈してしまう。ここが macOS で空振りした直接の理由だ。しかも、この誤判定は単なる小さなバグではない。侵入の最後の一押し、つまり外から入ってくる口を開ける処理が飛ぶので、攻撃者の手元には鍵だけが残る。
とはいえ、何も起きなかったわけではない。公式通知と Phorion の分析の両方で、攻撃者の SSH 公開鍵は authorized_keys に追記されている。さらに、永続化用の仕掛けやホスト情報の送信も行われたとされる。つまり、端末には「後で使うための材料」が残る。SSH がすでに有効だった端末、あるいは後から管理者が Remote Login を有効にした端末なら、その鍵はそのまま入口になる。
ここが少し嫌なところで、被害の大きさは「今回の実行時に SSH が立っていたか」に左右される。閉じていればリバーストンネルの先にある localhost:22 へ届かず、攻撃者はログインできない。開いていれば話は別だ。だから、空振りの Mac でも安心材料にはならない。鍵の残骸がある時点で、再点火の余地があるからだ。
Cursor 公式は、影響確認の手がかりをかなり具体的に出している。~/.ssh/authorized_keys に svc-telemetry があるかを見るだけでなく、改変された VSIX の SHA-256、攻撃者 IP 134.209.82.225、~/.config/.smt や ~/.config/.smtk、$TMPDIR/.stk_<10 hex>、macOS の com.apple.sysmond.plist など、複数の痕跡を並べている。これは、単発の接続有無よりも「設置された道具一式」を拾うための設計だ。
実務では、ここを雑に扱うと危ない。拡張を削除しただけで終えると、トンネル用のスクリプトや起動設定が生き残る可能性がある。さらに、端末から見える範囲の情報はすでに送られている前提で動くべきだ。ホスト名、ユーザー名、作業ディレクトリ、Git のメールアドレス、公開 IP まで収集されているので、資格情報の扱いも、端末の再利用も、通常より一段重く考えたほうがいい。
この件を「たまたま macOS の判定バグで助かった話」として終えるのは危うい。私なら、まず authorized_keys の中身を見て、svc-telemetry の有無でなく公開鍵そのものの指紋まで確認する。次に、拡張の削除だけで済ませず、永続化の痕跡と関連プロセスを洗う。最後に、その端末から触れた資格情報を順に更新する。ローカルの SSH が止まっていても、そこに置かれた鍵が消えない限り、後で再び扉になる可能性があるからだ。
今回の macOS では、管理者権限がなかったことで“入口を開く処理”だけが失敗した。だが、攻撃の設計そのものはかなり実用的で、拡張機能が読み込まれた瞬間に動き、端末を静かに作業用の足場へ変える。だから、この件から学ぶべきなのは「Mac では助かった」ではなく、「拡張の更新一本で、開発端末の信頼境界は簡単に崩れる」という事実のほうだ。