chrome-release-verify について
Electron メンテナー向けに、Chrome のリリース修正をブランチに対応付け、パッチをローカルで検証してプルリクエストを準備するスキルです。提案したバックポートを進める前に、ユーザーの承認を求めます。
主な機能
- 01CVE と修正の対応付け
- 02ブランチ履歴による修正確認
- 03ローカルのバックポートパッチ作成
- 04パッチ競合の解決
- 05パッチの検査と再エクスポート
- 06バックポート用プルリクエスト作成
活用シーン
- 01Electron リリースブランチ向け Chrome 修正の評価
- 02適用可能なセキュリティ修正のバックポート
- 03プッシュ前のパッチ検証
- 04検証済みバックポート PR の準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ electron/ electron --skill chrome-release-verifyインストール後、Claude Code で/chrome-release-verifyを入力して読み込まれたか確認します。
詳細
Chrome リリース → 検証済みバックポート PR
入力:$ARGUMENTS = <release-branch> <chrome-releases-blog-url>(例:41-x-y https://chromereleases.googleblog.com/2026/04/stable-channel-update-for-desktop_15.html)。どちらかが不足している場合は確認してください。
このフローはローカル優先です。すべてのパッチが e sync --3 で適用され、lint --patches に合格するまで、何もプッシュしません。
1. CVE → バグ → 修正 CL の対応付け
/chrome-release-cls <blog-url>(またはそのインライン手順)を実行して、/tmp/cve_bugs.txt(CVE|bug|severity|desc)と、バグごとの正規の修正 CL を作成します。各 CL について、repo(src/ 配下のパス:., v8, third_party/{skia,angle,pdfium,dawn}, third_party/libaom/source/libaom)と gerrit-host も記録してください。
ターゲットマイルストーンへのマージ CL が存在する場合は、それを優先してください(例:41-x-y が M146 に相当する場合、メイン CL より [M146] の cherry-pick を優先します)。すでにリベース済みで、競合する可能性がはるかに低いためです。Change-Id で git log --all --grep を実行するか、Gerrit の ?q=bug:<n> で探してください。Chrome がターゲットマイルストーンに修正をマージしていない場合でも、それだけを理由にスキップしてはいけません。Chrome のマージ期間は Electron のサポート期間より短いためです。メイン CL(または近隣マイルストーンへのリベース。手順 5 を参照)にフォールバックし、脆弱なコードがブランチに存在するかどうかは手順 3 で判断します。
2. 同期済みのワークツリーを準備する
e show configs に bp-<NN> があれば再利用し、なければ e worktree add bp-<NN> ~/src/electron-bp-<NN> --source <current> --no-sync を実行します。
cd <root>/src/electron
git fetch origin <branch>
git checkout -B security-backport/<branch>/<short-date> origin/<branch>
e use bp-<NN>
e sync 2>&1 | tee /tmp/bp_sync.log
同期に失敗し、NotADirectoryError: '<root>/src/.git/objects/info/alternates' が発生した場合は、bp 設定の env から GIT_CACHE_PATH を削除して再試行してください。
3. IN-TREE と NEEDS-BACKPORT を判定する
各バグについて、同期済みのリポジトリで次の 3 つを確認します。
git -C "$repo" log HEAD --since='1 year ago' -E --grep="\b${bug}\b" --format='%h %s'- Gerrit から Change-Id を取得し、
git log HEAD --grep="^Change-Id: ${cid}$"を実行します。 grep -rlE "(\b${bug}\b|${cid})" <root>/src/electron/patches/
いずれかでヒットした場合は IN-TREE です。すべて空の場合は NEEDS-BACKPORT です。
手順 1(または受け取った上流トリアージレポート)で RESTRICTED / 公開 CL なし とされた行は、引き継がれたものとして扱わず、ここで再調査してから分類してください。git -C "$repo" fetch origin と git -C "$repo" log --all --remotes -E --grep="(Bug|Fixed):.*\b${bug}\b" --format='%h %s' を実行し、chrome-release-cls スキルの gitiles_grep を chromium/src、v8、コンポーネントのリポジトリの refs/heads/main と branch-heads の参照に対して実行し、さらに Gerrit で ?q=bug:<id> / ?q=message:<id> を新たに検索してください。Gerrit の変更記録にはアクセス制限がかかっていても、修正コミットがすでに git で公開されていることはよくあります。また、実行中に制限が解除されることもあるため、以前の RESTRICTED 判定は手掛かりであって、結論ではありません。これらがすべて空の場合に限り、その行は RESTRICTED のままです。省略によって IN-TREE と判定してはいけません。人が後で確認できるよう、レポートに別途記載してください。
NEEDS-BACKPORT の各 CL について、ファイル一覧(/changes/<proj>~<cl>/revisions/current/files)も取得し、すべてのファイルが chrome/browser/、chrome/android/、ios/、または components/**/android/ 配下にある場合はスキップしてください。Electron ではこれらをコンパイルしません。
ここでテーブル(CVE | Sev | Bug | Component | Verdict | CL)と、提案するバックポート対象を報告し、続行前にユーザーの承認を得てください。
4. パッチをローカルに作成する(まだプッシュしない)
バックポートする各 CL について、raw パッチを取得し、patches/<dir>/ に書き込みます。
curl -s "https://${host}.googlesource.com/changes/${proj//\//%2F}~${cl}/revisions/current/patch" \
| base64 -d > "patches/${dir}/cherry-pick-${short}.patch"
echo "cherry-pick-${short}.patch" >> "patches/${dir}/.patches"
Gerrit ホストが e cherry-pick でサポートされていないリポジトリ(例:aomedia 上の libaom)では、代わりに同期済みサブリポジトリの HEAD に対して上流コミットを git cherry-pick し、その結果を git format-patch してください。
新たに作成した patches/<dir>/ がある場合は、エントリごとに 1 行のコンパクトな形式を維持して patches/config.json に追記します。
{ "patch_dir": "src/electron/patches/<dir>", "repo": "src/third_party/<dir-or-nested-path>" }
5. e sync --3 で検証する
e sync --3 2>&1 | tee /tmp/bp_sync3.log
Patch failed at NNNN <subject> が表示された場合:
- 失敗したリポジトリに
cdし、git diffで競合マーカーを確認します。 - テスト専用ファイル(例:
web_tests/VirtualTestSuites、コンテキストのずれがある*_unittest.cc):セキュリティ関連のハンクが問題なくマージされていれば、ours を採用します(git checkout --ours -- <file>)。 - 実質的なコードの競合:競合は、変更を取り下げる理由にはなりません。次の順に対応します。
- 対象マイルストーン上にある同じ Change-Id のマージ(Change-Id で
git log --all --grepを実行するか、Gerrit で?q=change:<Change-Id>を検索)に切り替えます。 - 近接するマイルストーン上にある同じ Change-Id(作者のリベース版。たとえば対象が M150 の場合は
[M152]の CL でも構いません。ステータスが NEW でも問題ありません)と、修正が前提としている前提 CL(修正対象のヘルパーやシグネチャを導入したリファクタリング)を確認します。修正をそのまま適用できるものを選び、レポートに前提 CL を記載します。 - それ以外の場合は、修正の意味をブランチのコードに手動で移植します。対象リポジトリでハンクを解決して、ピックのパッチファイル内に反映し、ピックしたコミットに取り込みます(
git commit --fixupと autosquash rebase を使用)。その後、再エクスポートします。上流コミットのヘッダーはそのまま保持し、パッチヘッダーにElectron adaptation notes (<branch>)の段落を追加して、すべての適応内容(メンバー名の変更、シグネチャの変更、ヘルパーのインライン化など)を記載します。機械的かつ構造的な変更のみを行い、修正が確認または保護する対象を絶対に変えず、上流の差分にない意味を決して作り出さないでください。その行をBACKPORTED (adapted)とし、レポートと PR 本文でレビュー担当者の注意を促します。適応したピックにも他と同じ基準が適用されます。e sync --3、lint --patches、および呼び出し元が要求するビルドゲートを通過させてください。
- 対象マイルストーン上にある同じ Change-Id のマージ(Change-Id で
- DROPPED にできるのは、次の 2 つの場合に限ります。(a) 脆弱性のあるコードがブランチに存在しない(ファイル、関数、機能が存在しない)、または (b) サブシステムの書き換えにより、修正を適用できる箇所がない。DROPPED とする各行には、該当する理由と証拠を記載します。取り下げたパッチは完全に削除してください(ファイルを削除し、
.patchesとconfig.jsonからも削除します)。 - 解決後は、
git add <files> && git -c commit.gpgsign=false am --continueを実行し、続けてe patches <repo>で解決済みパッチをエクスポートしてから、e sync --3を再実行します。問題がなくなるまで繰り返します。
6. エクスポート → lint → 再適用のループ
e patches all
node script/lint.js --patches # must exit 0
lint で指摘があった場合(通常は + で始まる行の末尾の空白)、修正するとパッチが書き込むバイト列が変わり、e patches が生成した index <old>..<new> のブロブハッシュが無効になります。.patch を手動で編集してそのままプッシュすると、ローカルでは lint に合格しても、CI の Apply Patches 再エクスポートチェックで index ハッシュの 1 行だけに差分が生じて失敗します。
そのため、エクスポート後に lint(または自分での編集)によって .patch ファイルを変更した場合は、もう一度ラウンドトリップしてください。
# fix the lint findings in patches/**/*.patch, then:
e sync # re-apply the edited patches (no --3 needed; they applied cleanly last time)
e patches all # re-export so index blob hashes match the edited content
node script/lint.js --patches # must now exit 0
git diff --quiet -- patches/ || { echo "patches changed again — repeat the loop"; }
lint --patches が終了コード 0 を返し、最後の e patches all の後に git diff -- patches/ が空になるまで繰り返します。それで初めて、パッチセットが CI で安定した状態になります。
7. コミット、プッシュ、PR
git add patches/
git commit -m "chore: cherry-pick <N> changes from <dirs>"
git push origin HEAD
gh pr create --repo electron/electron --base <branch> --head <this-branch> \
--title "chore: cherry-pick <N> changes from <dirs>" \
--label "<branch>" --label backport-check-skip --label semver/patch --label "security 🔒" \
--body-file /tmp/pr_body.md
PR の本文形式 — .github/PULL_REQUEST_TEMPLATE.md(Description of Change/Checklist/Release Notes セクション)に従ってください。形式に従っていない PR は自動的にクローズされます。
#### Description of Change
Backports the following changes:
* [`<shortCommit>`](<gerrit-CL-url>) from <patchDir> — <subject>
* [`<shortCommit>`](<gerrit-CL-url>) from <patchDir> — <subject> (adapted for <branch>; see patch header)
* ...
#### Checklist
- [x] I have filled out the PR description
- [x] [I have reviewed and verified the changes](https://github.com/electron/governance/blob/main/policy/ai.md)
#### Release Notes
Notes: Backported fixes from upstream Chromium and V8.
PR の本文では、セキュリティに関する表現を控えめにしてください。 PR は公開された時点で誰でも閲覧できますが、修正によってユーザーが保護されるのはリリース後です。その間にエクスプロイトの情報を広めないでください。具体的には、タイトル、本文、Notes: 行のいずれにも、CVE 番号、crbug.com へのリンク、「security」/「0-day」/深刻度を示す表現を含めないでください。security 🔒 ラベルは問題ありません(リリースの管理に使用します)。上流のコミットタイトルに「UAF」とあっても、そのまま記載してください。書き換えると、Gerrit CL との追跡可能性が損なわれます。含まれる修正内容に合うように Notes: の文言を調整してください(例:v8 のパッチがない場合は「and V8」を削除します)。
CVE と CL の対応関係は PR に記載しないでください。ローカルのメモファイル(/tmp/cve_cls.txt)に残し、理由とともに、修正内容を変更、削除、またはスキップしたものがあれば、それも含めてチャットでユーザーに報告してください。
作業が終わったら e use <previous> を復元してください。