brotli2crash

Activity, over time

Daily observations from the public event archive.

Attention

Daily stars & forks

Loading attention chart

Star accumulation

Cumulative stars

Loading star accumulation chart

Pull requests

Daily opens & merges

Loading pull requests chart

Conversations

Daily issues & comments

Loading conversations chart

Community

Daily accounts & reviews

Loading community chart

Releases

Daily releases

Loading releases chart

Mentions

2posts · 30d
Nov 40 posts
  1. Bluesky · · @plz.bsky.social

    Ohboy the plot thickens ikow/brotli2crash Trying my damndest to comprehend this proof...

  2. Zenn · · @nekoai_lab

    【要対応】Node.jsの脆弱性10件が修正。Claude Code・MCP利用者が今すぐ確認すべきこと TL;DR 2026年10月21日、Node.jsの深刻な脆弱性を含む10件が修正された。 修正版は v22.23.4 / v24.22.1 / v26.12.1。該当する古いNodeを使っているなら更新が必要 Nodeを更新しただけでは終わらない。 自分のMacでは、修正前のNodeで動くプロセスが19個残っていた Claude Code本体、MCPサーバー、Cursor CLI、公開アプリでは確認・更新する場所が異なる 本番のDockerイメージも、再ビルド・再デプロイしない限り古いまま残る この記事では、今すぐ確認する手順、実際に対応した結果、同じことを繰り返さないための仕組みをまとめた Node を上げた。19個、直っていなかった 10月23日、仕事のチャットに「Node.js が危ないのでアップデート必須。Claude Code を使っている人はガッツリ関係する。会社単位じゃなく個人単位で」と連絡が回ってきた。 自分も最初はこう思った。 「Claude Code って Node で動いてるんだっけ?」 「本体は勝手に更新されるんでしょ?」 「GitHub も見るの? GCP は? Vercel は?」 調べてみたら、答えはどれも「半分合ってる」だった。 自分の Mac を見たら、Node は修正前の 26.10.0 のまま。brew upgrade node で 26.12.1 に上げた。これで終わり、と思った。 念のためプロセスを数えた。 修正前の Node で動き続けているものが、19個あった。 Astro の dev サーバーが10個。Next.js が4個。Claude Code が裏で起動した MCP サーバーが5個。いちばん古いものは1週間前から動いていた。しかも最初に打ったコマンドでは、そのうち3個が見えていなかった。 極めつけは、この調べものに使っていた Claude Code 自身だ。スマホから使うために Mac mini で常駐させていた Remote Control の親プロセスが、1週間前の 2.1.292 のまま動いていた。claude update で新しい版を入れても、そこから起動するセッションは古いままだった(後述)。 アップデートは、インストールした時点では終わらない。この記事は、その話だ。 自分はどれ? 3つの質問で判定する 質問 はい → いいえ → ① Claude Code・Cursor・Codex などの AI ツールを使っている? A に該当。次の質問へ 次の質問へ ② ターミナルで node -v を打つと、バージョンが出る? B に該当。次の質問へ 次の質問へ(ただしアプリ同梱の Node は残る。後述) ③ Node で作ったアプリやサーバーを、ネットに公開している? C に該当 — そのうえで、node -v や本番の Node が v18・v20・v23・v25 なら D も当てはまる。修正版が出ない。 区分 誰 やること 所要 A AI ツールを使っている人 Claude Code・Cursor CLI・デスクトップアプリを最新に 5分 B PC に Node が入っている人(MCP サーバー、npx、npm で入れた CLI、dev サーバー) Node を更新して、動いているものを再起動 10〜20分 C Node のアプリを公開している人 本番の実行環境を更新して再デプロイ 環境しだい D Node 20 以前などを使っている人 22 / 24 系に乗り換え 半日〜 Claude Code 本体だけ使っている人は、まず A。たぶんこの層がいちばん多い。 ただ、Claude Code を入れるときに「Node も入れてね」と言われて Homebrew で入れた人は多いはず。その場合は B も当てはまる。node -v を一回打ってみてほしい。 結局、どこを見ればいいのか 見る場所は3層ある。 層 何を見る 見落としやすいもの ① PC(持っている台数ぶん) Claude Code の版、node -v、動いている Node、アプリ同梱の Node 普段使わないPC、起動しっぱなしの dev サーバー ② リポジトリ Dockerfile の FROM node:..、.nvmrc / .node-version、package.json の engines、GitHub Actions の node-version FROM node:20 のまま、node-version: 24.14.0 みたいな細かい固定 ③ 本番 実際に動いているランタイムの版 「Dockerfile は直したけど、まだデプロイしてない」 ②はリポジトリの置き場所でこう打てば一覧が出る。 grep -rnE "FROM node|node-version|\"node\":" \ --include=Dockerfile* --include=.yml --include=.yaml \ --include=package.json --include=.nvmrc --include=.node-version \ --exclude-dir=node_modules . 自分のリポジトリ(10本ちょっと)でやったら、こうなった。 本番が Cloud Run(自前の Dockerfile)で FROM node:20-alpine のもの:1本。修正が出ない系列。最優先 本番が Cloud Run で FROM node:22-alpine のもの:3本。イメージを作り直して再デプロイ CI で node-version: 24.14.0 に固定しているもの:1本。本番は Cloudflare Workers なので Node では動いていない。CI だけ上げればいい Python のサービス、静的サイト(Firebase Hosting):本番は関係なし CI(GitHub Actions)は、外から来たデータを展開する場面が少ないので優先度は低い。でも node-version の固定は、ついでに上げておく。 そもそも何が直ったのか Node.js の公式発表では、10件のうち4件が深刻度「高」だった。 CVE ざっくり言うと 危ない場面 CVE-2026-111497 Brotli(圧縮形式の一つ)を展開するとき、メモリの範囲外に書き込める 外から来た Brotli データを Node が展開するとき CVE-2026-106069 0127.0.0.1 みたいな変な書き方の IP アドレスで、TLS 証明書のチェックがずれる 接続先のホスト名を外部入力で決めていて、かつ通信経路を握られているとき CVE-2026-105483 全角数字の IP アドレスで、TLS 証明書のチェックがずれる(24 / 26 系だけ) 同上 CVE-2026-105482 dns.resolve が名前の途中の NUL 文字(\0)で切れる 「許可リストで名前をチェックしてから名前解決する」作りのとき 残り6件は中・低。HTTP の keep-alive、crypto.randomUUID()、権限モデルまわりなど。 修正版は v22.23.4 / v24.22.1 / v26.12.1。回避策は出ていない。上げるしかない。 Brotli のバグは、理屈の上では任意のコード実行までつながる種類のものだ。Node の発表でも「リモートからのコード実行を許す」と書かれている。ただ、10月23日時点で GitHub に公開されている PoC と解析を見ると、5本のうち4本は「リモートからのコード実行は成立していない。実際にはプロセスを落とせる(DoS)」という結論だった(条件を固めたローカル環境でなら実行できた、という報告はある)。落とせるだけでも、サーバーなら十分困る。 どんな場合に危ないのか ここがいちばん混乱しているところだと思う。 TLS と DNS の3件は、条件がかなり狭い。「接続先を外部入力で決めるサーバーを作っている」「経路上に攻撃者がいる」くらいの前提が要る。普通に使っているだけなら、ほぼ当たらない。 問題は Brotli の1件だ。こっちは入口が広い。 当たる:Node が外部のサイトやAPIを fetch() する Node の fetch() は、HTTPS のとき「Brotli で圧縮して送ってくれていいよ」とサーバーに伝える。サーバーが Brotli で返してきたら、中身を自動で展開する。 つまり、相手のサーバーが悪意を持っていたり、乗っ取られていたりしたら、fetch() しただけで細工したデータが届く。 当てはまるもの: URL を取りに行く MCP サーバー(Web取得、ブラウザ操作、スクレイピング系) 外部 API を叩くスクリプトやバッチ Claude Code に作らせた「URLを入れると要約するツール」みたいなもの 当たる:外からのリクエスト本文を展開するサーバー Express 5(body-parser 2.x)は、express.json() などのパーサーを使っていると、Content-Encoding: br のリクエスト本文を既定で展開する。 Express で API を公開しているなら、C に該当する。 ちなみに公開されている PoC(攻撃の実証コード)の一部も Express を使っている。ただし受け取った本文を自前の処理で Brotli 展開する作りで、body-parser の既定の動作を狙ったものではない。 当たる:受け取ったファイルを zlib で展開する アップロードされた .br ファイルを展開する、みたいな処理。これも外から来たデータの展開だ。 ほぼ当たらない:自分のPCの中だけで完結するもの localhost でしか見ていない dev サーバーが、外部と通信していないなら、細工したデータが届く経路がない。 ただし「dev サーバーの中で外部 API を fetch() している」なら当たる。Next.js のサーバー側で外部APIを呼んでいる、とか。けっこうある。 当たらない:Node を入れているだけ インストールされているだけで、何も動いていなければ攻撃は届かない。ただ、MCP サーバーは Claude Code を開くたびに裏で起動する。「動かしていないつもり」が一番あぶない。 Claude Code 本体の話:Node じゃなくて Bun 本体は Node を使っていない Claude Code の公式ドキュメントには、「インストールされた claude は Node を呼び出さない」とある。npm で入れた場合も、中身は同じネイティブバイナリだ。 だから「Node を更新すれば Claude Code 本体が直る」は、正しくない。 中の Bun にも、同じ Brotli のコードが入っていた Claude Code のネイティブ版は Bun で作られている。 その Bun にも、同じ Brotli ライブラリが入っていた。Bun の issue #46352 では「全リリースが影響を受ける」とされ、10月22日に修正がマージされた(日本時間11時ごろ)。修正を含む Bun v1.4.4 のリリースは同日19時ごろだ。 じゃあ Claude Code 本体で攻撃が届くのか。ここは分からない。Claude Code の中で、外から来た Brotli データを Bun が展開する場面があるのか。Anthropic は何も公表していない。 2.1.308 に上げた。直ったかは分からない 自分の Mac に入っていたのは 2.1.306。公開は10月21日(日本時間12時ごろ)で、Bun の修正より前だ。 claude update を打ったら 2.1.308 になった。 $ claude update Current version: 2.1.306 Updating to 2.1.308... Successfully updated from 2.1.306 to version 2.1.308 2.1.308 の公開は10月22日の13時半ごろ。Bun の修正マージよりは後、Bun v1.4.4 のリリースよりは前。リリースノートは「Bug fixes and reliability improvements」の1行だけだった。 なので言えるのは「最新にしておくのが、いまできる最善」まで。直ったとは言えない。 「本体は勝手に更新される」は本当か 入れ方による。公式ドキュメントを読むと、こうなっている。 入れ方 自動で更新される? 手で上げるコマンド 公式インストーラー(curl ... install.sh) される claude update npm される(書き込み権限があれば) npm install -g @anthropic-ai/claude-code@latest Homebrew(brew install --cask claude-code) 既定ではされない brew upgrade claude-code WinGet 既定ではされない winget upgrade Anthropic.ClaudeCode apt / dnf / apk されない OS のアップデートで Homebrew と WinGet は、CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE=1 を設定すると Claude Code が代わりに更新してくれる。 自分の Mac は公式インストーラー版で、9/26・10/7・10/16・10/22 と更新されていた。 それでも 2.1.306 で止まっていた。自動更新は「起動したときと、動いている間にときどき」見に行って、次に起動したときに切り替わる仕組みだからだ。急ぐなら claude update を手で打つ。 ちなみに配布には latest と stable(ふだんは約1週間遅れ)の2つのチャンネルがある。今回は10月22日の時点で、stable も 2.1.308 になっていた。 逆に Node は、誰も勝手に更新してくれない。Homebrew で入れたなら、brew upgrade を打つまで永遠に古いままだ。 手順 まず一発で確認する PC ごとに、これをターミナルに貼る。普段使わない PC も忘れずに。 Mac / Linux: echo "== Claude Code"; claude --version 2>/dev/null || echo "入っていない" brew list --cask 2>/dev/null | grep '^claude-code' && echo "↑ Homebrew 版。既定では自動更新されない" echo "== Node"; which -a node 2>/dev/null; node -v 2>/dev/null || echo "入っていない" echo "== Cursor CLI"; cursor-agent --version 2>/dev/null || echo "入っていない" echo "== 動いている Node"; ps -axo pid,lstart,command | grep -E '[n]ode |[n]ext-server' | cut -c1-150 Windows(PowerShell): "== Claude Code"; claude --version "== Node"; where.exe node; node -v "== 動いている Node"; Get-Process node -ErrorAction SilentlyContinue | Select-Object Id, StartTime, Path 最後の「動いている Node」の読み方: 起動時刻が Node をアップデートする前 → 古い Node で動いている。再起動する パスが /Applications/〜.app/ の中 → アプリが同梱している Node。アプリの更新を待つ パスが Homebrew の Caskroom の中 → Homebrew で入れたツール(Cursor CLI など)が同梱している Node。brew upgrade --cask <名前> で上がることがある コマンドの引数に node という文字を含むだけの別のプロセスも出てくる。パスを見て判断する next-server → Next.js の dev サーバー。名前に node が付かないので、grep node だけだと見逃す。自分はこれで3個見逃した 「入っていない」と出ても、それは PATH の上に無いというだけだ。アプリ同梱の Node、Docker、本番は別に見る(下の「Node を同梱しているアプリ」と C)。 A:AI ツール本体 claude update claude --version # 2.1.308 以降を推奨(修正が入ったかは未公表) Homebrew で入れた人は brew upgrade claude-code(latest 版なら claude-code@latest)、WinGet なら winget upgrade Anthropic.ClaudeCode。 開いている Claude Code は、一度閉じて開き直す。動いているプロセスは古い版のままだからだ。 Remote Control(claude remote-control)を常駐させている人は要注意だ。自分の Mac mini では、スマホから使うために claude remote-control を tmux の中で常駐させていた。これが10月16日に起動したまま、当時の 2.1.292 で動き続けていた。スマホから新しく作ったセッションも、全部この 2.1.292 で起動していた。claude update で 2.1.308 を入れても、常駐している親が古いままなら子も古い。 常駐している親ごと止めて、起動し直す。自分の環境(tmux セッション名 claude、LaunchAgent で起動)ならこうだ。動いているリモートのセッションは全部切れるので、作業が終わってから。 tmux kill-session -t '=claude' launchctl kickstart gui/$(id -u)/com.nekoai.remote-control # 自分で作った LaunchAgent の名前 ps -axo lstart,command | grep '[c]laude/versions/' # 新しい版で動いているか確認 Cursor を使っているなら CLI も。中に自前の Node を抱えている。 cursor-agent update # 公式インストーラーで入れた場合 brew upgrade --cask cursor-cli # Homebrew で入れた場合 自分の Mac では、cursor-agent update で 2026.10.22 版になって、中の Node が v26.8.1 から v26.12.1 に上がった。 デスクトップアプリも見ておく。10月23日、もう1台の Mac で Claude のデスクトップアプリを開いたら「Claude has an important security update」と出た。Mac mini のほうは、気づいたときには自動で入っていた。ChatGPT のデスクトップアプリにもアップデートが来ていた。中身が今回の件かは、どちらも公表されていない。Claude アプリの更新版(3.6556.1)の中の Node は v24.22.0 で、Node の修正版ではなかった。アプリのログを見ると、アプリに内蔵されている Claude Code が 2.1.304 から 2.1.308 に上がっていた。アプリの「新着情報」(10月22日付)には Node や Brotli の記載はなく、作業フォルダの権限や SSH まわりの変更・修正が並んでいた。「important」はそっちの話なのだと思う。それでも「important」と出ているなら入れる。 Mac の Claude アプリなら、画面上のメニューバーの「Claude」→「アップデートを確認…」→「再起動してアップデート」。アプリの中のアカウントメニューには無いので注意。 B:PC の Node まず、どこから入れた Node かを確認する。 which -a node ls -l "$(which node)" node -v ls -l の結果 入れ方 更新コマンド .../Cellar/node/... を指している Homebrew brew update && brew upgrade node ~/.nvm/... nvm 下を参照 fnm を含むパス fnm fnm install 24 && fnm default 24 ~/.volta/... Volta volta install node@24 mise を含むパス mise mise use -g node@24 /usr/local/bin/node で Cellar を指していない 公式インストーラー nodejs.org から最新版を入れ直す /usr/local/bin/node は、Intel Mac の Homebrew でもここに入る。ls -l で Cellar を指していたら Homebrew だ。Homebrew で node@22 や node@24 を入れているなら、brew upgrade node@24 のように指定する。 nvm は、入れるだけだと足りない。 nvm install 24 --reinstall-packages-from=current # npm -g で入れたものも引き継ぐ nvm alias default 24 nvm use 24 # 今のターミナルも切り替える プロジェクトの .nvmrc や、MCP の設定ファイルに ~/.nvm/versions/node/v22.x/... のような絶対パスを書いていたら、そっちも直す。古い版は nvm uninstall <古い版> で消せる。fnm・Volta・mise も、固定や絶対パスの事情は同じだ。 Windows はこう。 where.exe node の結果 入れ方 更新 C:\Program Files\nodejs\node.exe 公式インストーラー or winget winget list OpenJS で ID を確認して winget upgrade <ID>。無ければ nodejs.org から入れ直す ...\nvm... や nodejs へのリンク nvm-windows nvm install 24.22.1 → nvm use 24.22.1 .volta / fnm を含むパス Volta / fnm Mac と同じ winget の ID は、LTS 版なら OpenJS.NodeJS.LTS、最新版なら OpenJS.NodeJS。入れている方を上げる。 上げたら確認。 node -v v26.12.1 / v24.22.1 / v22.23.4 以降ならOK(v23・v25 は修正が出ないので D へ) ここからが本番。「まず一発で確認する」の最後の行をもう一度打つ。アップデートより前に起動したものは、全部古い Node で動いている。 Claude Code(ターミナル)→ /exit して起動し直す。裏の MCP サーバーも新しい Node で起動し直す Claude デスクトップアプリ・VS Code・Cursor → これらも MCP サーバーを起動している。ウィンドウを閉じるだけでなく、⌘Q(Windows はタスクトレイから終了)で完全に終了してから開き直す dev サーバー → Ctrl+C で止めて、もう一度起動 最後に、もう一度プロセスを確認する。自分で入れた Node のプロセスに、アップデートより前の起動時刻が残っていなければ、B は完了だ(アプリ同梱のものは残っていい)。 Node を同梱しているアプリ 自分で入れた Node とは別に、アプリが自前の Node を抱えていることがある。自分の Mac で、10月23日に見た版はこうだった。 アプリ 中の Node の版 Cursor の CLI(cursor-agent) v26.8.1 → 更新後 v26.12.1 Antigravity(Electron) v24.20.0 Grok Bot(SpaceXAI と Cursor が出しているアプリ。署名は Cursor の会社の Anysphere。Electron) v24.19.0 Claude デスクトップアプリ(Electron、更新版 3.6556.1) v24.22.0 ChatGPT デスクトップアプリ(中の補助ツール) v24.21.0(アプリ更新後も同じ) 版が修正前でも、そのアプリで攻撃が届くとは限らない。外から来た Brotli データをその Node で展開する場面があるかは、確認できていない。 Electron(VS Code、Cursor、Antigravity、Slack などの土台)は、10月23日時点の最新リリース(v45.0.0、10月21日)でも中の Node は 24.22.0 で、修正版ではなかった。 Cursor CLI 以外の同梱 Node は、こっちでは直せない。アップデートが来たら、すぐ入れる。それだけ。 Codex CLI は本体が Rust 製で、今回は関係ない。npm で入れた場合も、入口の小さなスクリプトが Node で動くだけだ。 C:公開しているアプリ 本番がどこで動いているかで変わる。 実行環境 自動で直る? やること Vercel 管理ランタイムに順次展開中。WAF ルールも入った Node 20 を使っているなら手動で移行。WAF は外向きの fetch() のレスポンスまでは守れない AWS Lambda 既定(Auto モード)なら自動で段階適用 Manual / Function update モードやコンテナイメージなら、再デプロイ・再ビルド Cloud Run(関数として、または --base-image 指定でソースからデプロイ) 自動ベースイメージ更新が有効なら反映される 設定を確認。今回の版の反映告知はまだ見つからなかった Cloud Run(自分の Dockerfile) 直らない 下の Docker と同じ。作り直して再デプロイ Firebase Functions 第2世代は Cloud Run の関数と同じ仕組みで、自動更新が既定で有効のはず コンソールでランタイムを確認し、心配なら再デプロイ Cloudflare Workers / Firebase Hosting(静的) 本番は Node で動いていない ビルドに使う Node だけ上げる Docker 公式イメージ node:22 / 24 / 26 は更新済み イメージを作り直して再デプロイ。node:20 は更新されない GitHub Actions setup-node の配布元には登録済み check-latest: true にするか、バージョンを固定で書く。ランナーのキャッシュに古い版が残っていることがある 自前サーバー 直らない B と同じ手順で更新して、プロセスを再起動 Docker は見落としやすい。FROM node:24 と書いてあっても、ビルドし直さないと古いイメージのままだ。 D:Node 20 以前を使っている Node 20 は2026年4月30日にサポートが終わっている。18・23・25 も終わっている。今回の修正は出ないし、今後も出ない。 Homebrew の node@20 は、10月28日に使えなくなる予定だ。 22 系か 24 系(どちらも長期サポート。26 系も10月28日に長期サポートに入る予定)に移す。破壊的変更があるので、テストを回しながら進める。今日すぐ終わる作業ではないので、それまでは「外部から来たデータを展開する処理」を止められないか考えておく。 確認コマンドと完了の判断は、教材にもまとめた。 nekoai-lab.github.io 時系列で見る 日時(日本時間) 出来事 2026年2月27日 Google の brotli リポジトリに、今回の修正のもとになるコミットが入る 10月14日 Node.js が「21日以降にセキュリティリリースを出す」と予告 10月21日 12時ごろ Claude Code 2.1.306 公開 10月21日 19時38分 Node.js v22.23.4 / v24.22.1 / v26.12.1 公開 10月22日 0時47分 最初の PoC リポジトリが GitHub に作られる 10月22日 4時27分 Google brotli が v1.2.1 / v1.1.1 / v1.0.10 を公開 10月22日 11時ごろ Bun が Brotli の修正をマージ 10月22日 13時半ごろ Claude Code 2.1.308 公開 10月22日 午後 Homebrew の node / node@24 / node@22 の修正版が配布される 10月22日 19時ごろ Bun v1.4.4 リリース 10月22日 23時ごろ CISA の評価は「悪用は確認されていない」 いくつか補足。 Brotli のバグは Node 固有じゃない。Google の brotli ライブラリ(1.0.3〜1.2.0)のバグで、CVE の採番も Google だ。CVSS 4.0 では 9.2(Critical)と付いていて、Node 側の評価は High。Brotli を使っている他のソフトも、同梱しているバージョンしだいで影響を受ける。 Node の発表では、Node への報告者として OpenAI の Codex Security チームの名前が載っている。上流の修正は2月に Google の開発者が入れていた。誰が最初に見つけたのかは、どの一次ソースにも書かれていない。 修正のもとになるコードは2月に brotli のリポジトリに入っていた。ただ、そのときはセキュリティ修正として出ていない。セキュリティ修正として世に出たのは10月21日の Node が最初で、brotli 自体のリリースはその翌日だった。 やった結果(実録) 対応は10月23日の朝の数時間。Mac 2台と本番4本。 対象 前 後 Mac mini の Node(Homebrew) v26.10.0 v26.12.1 Mac mini の Claude Code 2.1.306 2.1.308 Mac mini の Cursor CLI 同梱の Node v26.8.1 v26.12.1 Mac mini の Claude デスクトップアプリ 3.1623.4 3.6556.1(自動で更新。内蔵の Claude Code は 2.1.308) Mac mini の起動しっぱなしの Node 19個(最初のコマンドでは16個しか見えなかった) dev サーバー14個を止めた(親のプロセスも含めて15個を kill)。Claude アプリの MCP 1個はアプリの再起動で消えた。残りの MCP 4個は Remote Control を起動し直して消す MacBook Pro の Claude Code 2.1.283(9月26日の版) 2.1.308 MacBook Pro の Node v24.14.0(公式 pkg) Homebrew の v26.12.1 に切り替え MacBook Pro の起動しっぱなしの Node(全部 MCP サーバー) 11個(うち5個は9月19日から) 0個 本番(Cloud Run 4本) node:20 1本、node:22 3本 全部 22.23.4 で作り直してデプロイ。版チェック入り ChatGPT・Antigravity・Grok Bot の同梱 Node 修正前 アプリの更新待ち MacBook Pro はひどかった。 Claude Code は1か月前の版。Node で動いていた MCP サーバー11個のうち5個は、1か月以上前の9月19日から動き続けていた。その中には、ブラウザでページを取りに行く playwright-mcp もいた。今回のバグにいちばん当たりやすい種類だ。 Mac を閉じずにスリープで使い続けていると、こうなる。自動更新は「次に起動したとき」にしか効かない。 再発防止:「入れた」と「動いている」の差を仕組みで埋める 今回の穴は、どれも同じ形をしていた。 Node は上げた。でも動いているプロセスは古いまま Claude Code は上げた。でも常駐している親は古いまま Dockerfile は合っている。でも本番のイメージは作り直していない 自動更新はある。でも閉じないから効かない 人が気をつけて防ぐのは無理だと思った。なので仕組みにした。 1. Node の入れ方を全部の Mac で揃えた Mac mini は Homebrew、MacBook Pro は nodejs.org の公式インストーラーだった。入れ方が違うと、更新の手順も違う。だから後回しになる。 MacBook Pro を Homebrew に切り替えた。npm ls -g --depth=0 で、公式インストーラー側に自分で入れたツールが無いことを確かめてから。 以下は Apple Silicon の Mac(Homebrew が /opt/homebrew)で、公式インストーラーから乗り換える場合だ。Intel Mac は Homebrew 自体が /usr/local に入るので、この rm を打つと Homebrew の Node まで消える。先に brew --prefix が /opt/homebrew と出ること、ls -l /usr/local/bin/node が Cellar を指していないことを確かめる。 brew install node 公式インストーラーの Node を消す(npm -g で入れたものがあれば、先に控えておく) sudo rm -rf /usr/local/bin/node /usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/corepack \ /usr/local/lib/node_modules/npm /usr/local/lib/node_modules/corepack \ /usr/local/include/node /usr/local/share/doc/node /usr/local/share/man/man1/node.1 ターミナルを開き直して which -a node # /opt/homebrew/bin/node だけになれば OK これで、どの Mac も brew upgrade node の1行で済む。 2. 本番の Dockerfile に「古い Node なら作らない」を入れた FROM node:22-alpine と書いていても、作り直さなければ古いまま。逆に、キャッシュや取り違えで古いイメージが混ざることもある。 なので、本番のイメージを作るときに Node の版を確かめて、修正前なら止めるようにした。実行ステージの FROM の直後に1行足すだけだ。 FROM node:22-alpine AS runner Node.js 2026-10-21 のセキュリティ修正より前の版では作らない RUN node -e "const m={22:[23,4],24:[22,1],26:[12,1]};const [a,b,c]=process.versions.node.split('.').map(Number);const min=m[a];const ok=a>26||(min&&(b>min[0]||(b===min[0]&&c>=min[1])));if(!ok){console.error('Node '+process.version+' は修正より前か、サポート外');process.exit(1)}" 22.23.4・24.22.1・26.12.1 より前と、20 系などの修正が出ない系列は、ここでビルドが止まる。4本とも入れて、作り直し、デプロイまで通した。 このチェックが効くのは、作り直すときだけだ。作り直していない本番が古いままなのは、これでは分からない。 次は Dependabot に FROM node:.. を見張らせて、新しいイメージが出たら PR が自動で立つようにする(これから)。 3. 週1回、まとめて上げて「古いまま動いているもの」を探す 2つのスクリプトを作った。 weekly-update:Homebrew で入れたもの全部(Node 以外も)、Claude Code、Cursor CLI を上げる。macOS のアップデートが来ていれば知らせる(入れはしない。再起動が要るから) stale-procs:更新したのに、古い版のまま動いているプロセスを探す stale-procs の考え方は単純だ。プロセスの実行ファイルを lsof で調べて、いまの node の実体と違えば古い。Homebrew のものなら、Cellar/<名前>/<版> が opt/<名前> の指している版と違えば古い。Node や Python に限らず、Homebrew で入れたもの全部に使える。 Node だけなら、これで同じことが分かる。 cur=$(realpath "$(command -v node)") for pid in $(pgrep -f 'node|next-server'); do exe=$(lsof -a -p "$pid" -d txt -Fn 2>/dev/null | sed -n 's/^n//p' | head -1) case "$exe" in /Cellar/node/bin/node|/usr/local/bin/node|/.nvm//bin/node) [ "$(realpath "$exe" 2>/dev/null || echo "$exe")" != "$cur" ] && echo "$pid 古い Node: $exe" ;; esac done next-server のように名前を変えているプロセスも、実行ファイルで見るので拾える。アプリ同梱の Node は、自分では直せないので数えない。 ただし、これで分かるのは Homebrew と nvm で入れた Node だけだ。公式インストーラーの Node は同じ場所に上書きされるので、この比べ方では新旧を見分けられない。fnm・Volta・mise も、この短い版では対象にしていない。その場合は、プロセスの起動時刻が Node を上げた時刻より前かどうかで判断する。 結果はスマホに通知する。ただ、普段から通知は短すぎて読めていなかった。「更新されたな」と分かるだけで、何をすればいいかは分からない。なので、通知だけで次の行動が決まる形にした。 古い版のまま動いているもの 9 件 ・Remote Control・アプリから起動したセッション 4件(claude 2.1.292)  → 親(Remote Control)を作り直すか、そのセッションを閉じる ・MCP サーバー 4件(mcp-pdf-server/node 26.10.0_1)  → 起動したアプリやセッションを開き直す ・Remote Control の親 1件(claude 2.1.292)  → tmux のセッションを作り直す 4. 通知に「プロセスの引数」を出してはいけなかった このスクリプトは Claude Code で書いて、レビューは別の AI(Codex)にさせている。そのレビューで2回止められた。 1回目は、通知にプロセスのコマンドをそのまま載せていた。node app.js --password xxx のような起動のしかたをしていたら、パスワードがログとスマホの通知に流れる。 2回目は、それを直したつもりで「引数のうち、ハイフンで始まらない最初のもの」をスクリプト名として出していた。node -e 'key="..."' のように中身を直接渡すと、そのコードが名前として出る。 最後は「実在するファイルのときだけファイル名を出す。それ以外は node」にして通った。 プロセスの一覧を通知やログに出すスクリプトは、引数を出した時点で秘密が漏れる道になる。自分のレビューだけだったら、2回とも素通りしていたと思う。 5. 片付けをどこまで自動にするか(これから) 通知が来ても、止めるのが人の手作業なら、結局また溜まる。かといって、全部を自動で止めると作業中の dev サーバーやセッションが切れる。なので3段階に分けた。 段階 対象 誰が 全自動 起動した元がもういなくて取り残された古いプロセス。使われていないときの Remote Control の親 週1回の自動実行。止めたものは通知で報告 ひと言で 開いているセッションの MCP、dev サーバー 通知を見て、AI に「古いの片付けて」と頼む。一覧を見せて確認してから止める 人が決める デスクトップアプリ、macOS のアップデート 自分。通知に「何をすればいいか」が書いてある MacBook Pro の11個(うち5個は9月19日から)は、たぶん「全自動」で消える種類だった。これを作れば、今回の後片付けの大半は、寝ている間に終わる。 この部分は、設計まで書いて Codex に引き継いだ。 32リポジトリぶんの依存を、そのあとどう見回るようにしたかは、続きに書いた。 zenn.dev まとめ AI ツールを使っている人:claude update、Cursor CLI、デスクトップアプリを最新に。開き直す Node が入っている人:Node を上げて、動いているものを全部再起動。アプリ同梱の Node はアプリの更新で 公開している人:本番の実行環境を確認して、再デプロイ。Docker は作り直す Node 20 以前の人:今回は直らない。乗り換える 全員:「入れた」と「動いている」の差は、気合いでは埋まらない。週1回の更新と、古いまま動いているものの検出を仕組みにしておく アップデートは、インストールした時点では終わらない。 古いプロセスを止めた時点で、やっと終わる。 参考 Node.js — October 2026 Security Releases google/brotli v1.2.1 CVE-2026-111497(CVE.org API) oven-sh/bun #46352 — Brotli の脆弱性 Bun v1.4.4 ikow/brotli2crash — PoC と解析(実質 DoS とする例) hypnguyen1209/CVE-2026-111497 — Express を使った PoC Claude Code — セットアップ(ドキュメント) anthropics/claude-code — Releases expressjs/body-parser — read.js Electron v45.0.0 SpaceXAI and Cursor Launch Grok Bot Agent App in Beta(AI Weekly) Vercel — Node.js security advisory AWS Lambda — ランタイムの更新 Cloud Run — 自動ベースイメージ更新 actions/setup-node — check-latest Node.js リリーススケジュール

    4 likes

Latest stargazers

The last 10 distinct accounts we observed this year.

Most active participants

PR, issue, comment & review events in the past year.

Packages

No packages found.

README badges

Embed a badge in your README or website.

Live mentions · last 30 days
ikow/brotli2crash mentions in the last 30 days