Marimo脆弱性CVE-2026-39987——公開10時間でroot奪取が始まった
CVSS 9.3。公開からわずか9時間41分で初回エクスプロイト。認証情報の窃取は3分以内に完了——CVE-2026-39987は、開発者が日常的に使うPythonノートブックツールが、いかに簡単に「侵入の入口」へ変わるかを示す衝撃的な事例だ。
2026年4月8日、オープンソースのリアクティブPythonノートブックMarimoに認証なしリモートコード実行(RCE)脆弱性が公開された。WebSocketエンドポイント /terminal/ws が認証チェックを一切行わず、未認証の攻撃者に完全なPTY(疑似端末)シェルを提供してしまう。しかもデフォルトのDockerイメージはroot権限で動作するため、シェルを取得した時点でホスト全体の制御権を握られる可能性がある。
本記事では、この脆弱性の技術的メカニズム、実際に観測された攻撃パターン、そして日本のデータサイエンティスト・開発者が今すぐ取るべき対策を徹底解説する。
Marimoとは何か
次世代Pythonノートブック
Marimoは、Jupyter Notebookに代わるリアクティブPythonノートブックとして注目を集めているオープンソースプロジェクトだ。GitHubスターは急速に増加しており、データサイエンスやAI/ML開発の現場で採用が広がっている。
Marimoの最大の特徴はリアクティブ実行だ。あるセルのコードを変更すると、そのセルに依存する他のセルが自動的に再実行される。Jupyter Notebookでありがちな「セルの実行順序を間違えて結果がおかしくなる」問題を根本から解決している。
さらに、ノートブックは純粋なPythonファイルとして保存されるため、Git管理が容易だ。SQLのネイティブサポート、インタラクティブなUI要素(スライダー、ドロップダウン)、Webアプリとしてのデプロイ機能なども備えている。
なぜMarimoが狙われたのか
Marimoが攻撃対象として魅力的な理由は明確だ。
- AI/ML環境との共存: MarimoはLLMフロントエンド、AIオーケストレーション、ソースコードリポジトリなどと同一ホストに配置されることが多い
- 機密データへのアクセス:
.envファイル経由でクラウド認証情報、APIキー、データベース接続文字列などが取得可能 - root実行がデフォルト: 公式Dockerイメージがroot権限で動作するため、侵害時の被害が最大化する
- データサイエンティストのセキュリティ意識: 開発者と比較して、データサイエンティストはインフラセキュリティへの注意が不足しがちな傾向がある
CVE-2026-39987の技術的詳細
WebSocket認証の致命的なギャップ
CVE-2026-39987の核心は、MarimoのWebSocketエンドポイント間の認証実装の不整合にある。
Marimoには複数のWebSocketエンドポイントが存在する。メインのセッション用 /ws エンドポイントは WebSocketConnectionValidator.validate_auth() を正しく呼び出し、認証トークンを検証する。しかし、ターミナル機能を提供する /terminal/ws エンドポイントは、この認証フローを完全にスキップしていた。
/terminal/ws が行うチェックは2つだけだ。
- Marimoが「編集モード」で動作しているか
- 現在のプラットフォームがPTYをサポートしているか
認証トークンの検証は一切行われない。つまり、編集モードで動作しているMarimoインスタンスに対して、誰でもWebSocket接続を確立し、完全なシェルアクセスを取得できるのだ。
Starletteミドルウェアの落とし穴
問題をさらに複雑にしているのが、MarimoのWebフレームワークであるStarletteの AuthenticationMiddleware の挙動だ。
通常のHTTPリクエストでは、ミドルウェアが認証に失敗したリクエストを拒否する。しかしWebSocketアップグレードリクエストの場合、ミドルウェアは接続を拒否せず、単に「未認証」というマークを付けるだけだ。実際の接続拒否はエンドポイントレベルで行う必要がある。
/ws エンドポイントはこの設計を理解し、エンドポイント内で validate_auth() を明示的に呼び出していた。しかし /terminal/ws はこのステップを実装していなかった。WebSocket認証がHTTP認証とは本質的に異なるという点を開発者が見落としたことが、この脆弱性の根本原因だ。
この図は、正常な /ws エンドポイントと脆弱な /terminal/ws エンドポイントの認証フローの違い、および攻撃者がシェルを取得した後の行動パターンを示しています。
攻撃の具体的フロー
攻撃は以下の4ステップで完了する。
- WebSocket接続: 攻撃者が
ws://<host>:<port>/terminal/wsへ接続を要求 - 認証バイパス: サーバーが認証チェックなしで接続を受け入れる
- PTY割り当て: 完全な疑似端末(PTY)とシェルが攻撃者に提供される
- 任意コマンド実行: Marimoプロセスのユーザー権限(デフォルトDockerではroot)で任意のコマンドを実行
特筆すべきは、この攻撃に特別なエクスプロイトコードが不要だという点だ。WebSocketクライアントで接続するだけで攻撃が成立する。
公開から10時間——驚異的な悪用スピード
Sysdigハニーポットの観測記録
Sysdig脅威研究チームは、CVE-2026-39987の公開直後からハニーポット環境で攻撃の観測を開始した。その結果は衝撃的だった。
公開からわずか9時間41分で初回エクスプロイトが観測された。
さらに注目すべきは、この時点で公開されたPoCコード(概念実証コード)は存在しなかったことだ。攻撃者はセキュリティアドバイザリの技術的記述のみから、独自にエクスプロイトを作成した。
最初の12時間で125のIPアドレスから偵察活動が観測されており、攻撃者コミュニティがいかに迅速にアドバイザリ情報を消化し行動に移すかを如実に示している。
攻撃者の行動パターン
ハニーポットで観測された攻撃者の行動は、自動化スクリプトではなく手動による方法論的な操作の特徴を示していた。
第1段階——偵察(初回接続直後):
pwd(現在のディレクトリ確認)whoami(実行ユーザーの確認)ls(ファイルシステムの探索)
第2段階——認証情報窃取(接続から3分以内):
.envファイルの内容読み取り(クラウド認証情報、APIキー)- SSH鍵ファイルの探索(
~/.ssh/) - 各種設定ファイルの読み取り
第3段階——再接続(約1時間後):
- 同じエクスプロイト手法で再度接続
- さらなるファイル探索と情報収集
この図は、脆弱性公開から悪用開始までのタイムラインと、公開インスタンスの影響調査結果を示しています。
公開インスタンスの実態
セキュリティ企業Endor Labsの調査によると、インターネット上で到達可能な186個のMarimoインスタンスに対して未認証の /terminal/ws アップグレード試行を実施した結果、30件(約16%)で接続が成功した。これは編集モードで稼働しているインスタンスの存在を強く示唆している。
16%という数字は一見少なく見えるかもしれないが、各インスタンスがAI/MLワークロードやクラウド認証情報を扱っている可能性を考えると、30件のroot権限付きシェルがインターネットに公開されている状態は極めて深刻だ。
過去の開発ツール脆弱性との比較
開発ツールやノートブック環境の脆弱性は、CVE-2026-39987が初めてではない。近年の主要な脆弱性と比較してみよう。
| CVE | 対象 | CVSS | 脆弱性タイプ | 悪用までの時間 | 影響範囲 |
|---|---|---|---|---|---|
| CVE-2026-39987 | Marimo | 9.3 | 認証なしRCE(WebSocket) | 9時間41分 | rootシェル取得 |
| CVE-2026-34040 | Docker Engine | 8.8 | AuthZバイパス | 数日 | 特権コンテナ作成 |
| CVE-2024-3568 | Jupyter Server | 7.5 | SSRF | 数週間 | 内部ネットワーク探索 |
| CVE-2024-35178 | Jupyter Notebook | 7.8 | 認証バイパス | 数日 | コード実行 |
| CVE-2023-40170 | JupyterHub | 7.6 | XSS→権限昇格 | 数週間 | マルチユーザー環境侵害 |
| CVE-2022-39286 | Jupyter Core | 8.8 | ファイル上書き | 数日 | 任意コード実行 |
CVE-2026-39987が突出している点は3つある。
- CVSSスコアの高さ: 9.3は開発ツール脆弱性としては異例の高さだ
- 悪用までのスピード: PoCなしで10時間以内というのは、攻撃者の技術力と動機の高さを示している
- 攻撃の容易さ: WebSocketクライアントで接続するだけで完全なシェルが取得でき、高度な技術力は不要
WebSocket認証の設計教訓
なぜこの脆弱性が生まれたのか
CVE-2026-39987は単なる「認証の付け忘れ」ではなく、WebSocketプロトコルの認証設計に関する構造的な理解不足が原因だ。
HTTPリクエストとWebSocketの根本的な違い:
- HTTPリクエスト: 短命(リクエスト→レスポンスで終了)。ミドルウェアが各リクエストに同期的に認証を適用できる
- WebSocket: アップグレード後は長命の双方向パイプになる。「アップグレード時点での」明示的な身元確立が必須
多くのWebフレームワークのミドルウェア(今回のケースではStarlette)は、HTTPリクエストに対しては認証失敗時にリクエストを拒否する。しかしWebSocketアップグレードの場合、プロトコルの性質上、ミドルウェアは接続を拒否せずに「未認証」フラグを立てるだけにとどまることがある。
この設計パターンは、開発者にエンドポイントレベルでの明示的な認証チェックを要求する。/ws の開発者はこれを理解していたが、/terminal/ws の開発者は見落としたのだ。
他のプロジェクトへの教訓
この脆弱性から得られる教訓は、Marimoだけにとどまらない。
- WebSocketエンドポイントの認証は個別に検証すべき: ミドルウェアに依存せず、各エンドポイントで認証を明示的にチェックする
- コードレビューでWebSocketエンドポイントを重点的に確認: HTTPとWebSocketの認証処理が一貫しているか検証する
- 最小権限の原則を適用: Dockerイメージをroot以外のユーザーで実行する
- セキュリティテストにWebSocketを含める: ペネトレーションテストでWebSocketエンドポイントを忘れずにテストする
影響範囲と修正方法
影響を受けるバージョン
- 影響範囲: Marimo 0.20.4以前の全バージョン
- 修正バージョン: Marimo 0.23.0
修正内容は、ターミナルWebSocketの認証を他のWebSocketエンドポイントと統一し、validate_auth() を /terminal/ws でも呼び出すようにしたものだ。
即座に行うべき対策
1. バージョンアップグレード:
pip install --upgrade "marimo>=0.23.0"
2. 暫定的な緩和策(即座にアップグレードできない場合):
/terminal/wsエンドポイントへの外部アクセスをファイアウォールまたはリバースプロキシでブロック- Marimoインスタンスを外部ネットワークから隔離
3. 事後対応(すでに公開運用していた場合):
.envファイル内のすべてのシークレットをローテーション(APIキー、データベースパスワード、クラウド認証情報)- SSH鍵の再生成
- WebSocket接続ログの確認(
/terminal/wsへの不審な接続がないか) - 同一ホスト上の他のサービスへの横展開がないか調査
日本のデータサイエンティストへの影響
日本での利用状況
Marimoは日本のデータサイエンスコミュニティでも徐々に採用が広がっている。特に以下のユースケースで利用されることが多い。
- AI/MLモデルの実験・プロトタイピング: Jupyter Notebookからの移行先として
- データ分析ダッシュボード: リアクティブ性を活かしたインタラクティブなレポート
- LLMアプリケーションの開発: AIオーケストレーションのフロントエンドとして
- チーム内のデータ共有: Webアプリとしてデプロイし、非エンジニアにもアクセスを提供
日本特有のリスク
日本のデータサイエンス環境では、以下の点でリスクが高まる可能性がある。
1. クラウド環境での無防備なデプロイ: AWSやGCPのVMにMarimoをデプロイし、セキュリティグループの設定が甘いケースが散見される。特にPoC(概念実証)段階のプロジェクトでは「一時的だから」とセキュリティ設定を省略することが多い。
2. 個人情報保護法との関連: Marimoで扱うデータに個人情報が含まれている場合、CVE-2026-39987を通じた情報漏洩は改正個人情報保護法における安全管理措置義務違反に該当する可能性がある。
3. サプライチェーンリスク: 企業のMLパイプラインにMarimoが組み込まれている場合、ノートブック環境の侵害がモデルの改ざんやデータポイズニングにつながるリスクがある。
4. セキュリティチームとの連携不足: 多くの日本企業では、データサイエンスチームとセキュリティチームが別組織として運営されており、開発ツールの脆弱性情報が適切に共有されない傾向がある。
企業が取るべきアクション
日本企業のデータサイエンスチームは、今回の脆弱性を契機に以下の対応を検討すべきだ。
- ツール棚卸し: 社内で利用されているノートブック環境(Marimo、Jupyter、Colab等)の一覧を作成し、バージョンを管理する
- ネットワーク分離: データサイエンス環境をインターネットから直接アクセスできないネットワークセグメントに配置する
- セキュリティアドバイザリの監視体制: 利用ツールのCVE情報を自動的にキャッチする仕組み(GitHub Security Advisories、1Password等のシークレット管理ツールとの連携)を構築する
まとめ——10時間の猶予すらない時代の対策
CVE-2026-39987は、脆弱性公開から悪用までの「猶予時間」がもはや数時間しかないことを改めて突きつけた。PoCコードの公開を待たず、アドバイザリの技術的記述だけから攻撃者がエクスプロイトを作成する時代だ。
今すぐ実行すべきアクションステップ
- Marimoのバージョンを確認する:
pip show marimoでバージョンを確認し、0.23.0未満であれば即座にアップグレードする - 公開インスタンスを特定する: 自社環境でインターネットに公開されているMarimoインスタンスがないか、ネットワークスキャンで確認する
- シークレットをローテーションする: 過去にMarimoを公開運用していた場合、
.envファイル内の認証情報、SSH鍵、APIキーをすべて再生成する - WebSocket監視を導入する: WAFやリバースプロキシで
/terminal/wsへのアクセスを監視・制限するルールを追加する - 開発ツールのセキュリティポリシーを策定する: Jupyter、Marimo、VS Code Serverなどの開発ツールをデプロイする際のセキュリティ基準を明文化する
「便利な開発ツール」が「攻撃者にとっても便利なバックドア」になりうることを、CVE-2026-39987は教えてくれている。データサイエンティストであっても、インフラセキュリティは他人事ではない。
「セキュリティ」カテゴリの記事
- セキュリティ
FortiClient EMSにCVSS 9.1のゼロデイ——認証不要で任意コード実行
- セキュリティ
Smart Slider 3 Proが乗っ取られた——90万サイトに迫るバックドアの全貌
- セキュリティ
偽WhatsAppアプリでスパイウェア配布——イタリア企業SIOが200人を標的に
- セキュリティ
React2ShellでNext.js 766ホスト侵害——CVSS 10.0の認証情報窃取攻撃
- セキュリティ
ロシアAPT28が家庭用ルーターを乗っ取りM365認証を大量窃取
- セキュリティ
Docker脆弱性CVE-2026-34040——1リクエストでホスト全権奪取の衝撃