/chrome-release-verify
End-to-end Chrome security backport for an Electron release branch. Given a Chrome Releases blog URL and a branch (e.g. 41-x-y), determines which CVE fixes are missing from the *actual synced source*, writes the cherry-pick patches locally, validates them with `e sync --3` +
Claude Code
$ npx -y skills add electron/electron --skill chrome-release-verify --agent claude-code
Codex
$ npx skills add electron/electron --skill chrome-release-verify -a codex -y
Cursor
$ npx skills add electron/electron --skill chrome-release-verify -a cursor -y
Gemini CLI
$ npx skills add electron/electron --skill chrome-release-verify -a gemini-cli -y
GitHub Copilot
$ npx skills add electron/electron --skill chrome-release-verify -a github-copilot -y
OpenCode
$ npx skills add electron/electron --skill chrome-release-verify -a opencode -y
Windsurf
$ npx skills add electron/electron --skill chrome-release-verify -a windsurf -y
SKILL.md
chrome-release-verify.SKILL.mdname: chrome-release-verify
description: End-to-end Chrome security backport for an Electron release branch. Given a Chrome Releases blog URL and a branch (e.g. 41-x-y), determines which CVE fixes are missing from the *actual synced source*, writes the cherry-pick patches locally, validates them with `e sync --3` + `lint --patches`, then pushes a single PR. Use when asked to backport a Chrome security release to N-x-y, "is CVE-X already in N-x-y?", or to produce/validate the cherry-pick set for a release branch.
Chrome Release → Validated Backport PR
Input: `$ARGUMENTS` = `<release-branch> <chrome-releases-blog-url>` (e.g. `41-x-y https://chromereleases.googleblog.com/2026/04/stable-channel-update-for-desktop_15.html`). Ask if either is missing.
The flow is **local-first**: nothing is pushed until every patch applies via `e sync --3` and passes `lint --patches`.
1. Map CVE → bug → fix CL
Run `/chrome-release-cls <blog-url>` (or its inline procedure) to produce `/tmp/cve_bugs.txt` (`CVE|bug|severity|desc`) and a per-bug canonical fix CL. For each CL also note `repo` (path under `src/`: `.`, `v8`, `third_party/{skia,angle,pdfium,dawn}`, `third_party/libaom/source/libaom`) and `gerrit-host`.
**Prefer the target-milestone merge CL** if one exists (e.g. on `41-x-y` ≈ M146, prefer the `[M146]` cherry-pick over the main CL) — it's already rebased and far less likely to conflict. Find it via `git log --all --grep` on the Change-Id, or Gerrit `?q=bug:<n>`. If Chrome did _not_ merge a fix to the target milestone, that is **not** by itself a reason to skip — Chrome's merge window is shorter than Electron's support window. Fall back to the main CL (or a nearby-milestone rebase, see step 5) and let step 3 decide whether the vulnerable code exists on the branch.
2. Prepare a synced worktree
Reuse `bp-<NN>` from `e show configs` if present, else `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
If sync fails with `NotADirectoryError: '<root>/src/.git/objects/info/alternates'`, remove `GIT_CACHE_PATH` from the bp config's `env` and retry.
3. Verify IN-TREE vs NEEDS-BACKPORT
For each bug, three checks against the **synced** repo:
1. `git -C "$repo" log HEAD --since='1 year ago' -E --grep="\b${bug}\b" --format='%h %s'` 2. Fetch Change-Id from Gerrit, then `git log HEAD --grep="^Change-Id: ${cid}$"` 3. `grep -rlE "(\b${bug}\b|${cid})" <root>/src/electron/patches/`
Any hit ⇒ IN-TREE. All empty ⇒ NEEDS-BACKPORT.
Rows that step 1 (or an upstream triage report you were handed) left as **RESTRICTED / no public CL** are not inherited — re-resolve them here before classifying. Run `git -C "$repo" fetch origin` and `git -C "$repo" log --all --remotes -E --grep="(Bug|Fixed):.*\b${bug}\b" --format='%h %s'`, the `chrome-release-cls` skill's `gitiles_grep` on `refs/heads/main` and the branch-heads refs of `chromium/src`, `v8` and the component's repo, and a fresh Gerrit `?q=bug:<id>` / `?q=message:<id>` query. The Gerrit change record is often restricted while the fix commit is already public in git, and restrictions lift during a run, so an earlier RESTRICTED verdict is a hint, not a result. A row stays RESTRICTED only when all of those are empty; it is never IN-TREE by omission — list it separately in the report so a human can follow up.
For each NEEDS-BACKPORT CL, also fetch its file list (`/changes/<proj>~<cl>/revisions/current/files`) and **skip** if every file is under `chrome/browser/`, `chrome/android/`, `ios/`, or `components/**/android/` — Electron doesn't compile those.
Report the table now (`CVE | Sev | Bug | Component | Verdict | CL`) and the proposed backport set; get user sign-off before continuing.
4. Write patches locally (no push yet)
For each backport CL, fetch the raw patch and write it into `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"For repos with no Gerrit host `e cherry-pick` supports (e.g. **libaom** on aomedia), instead `git cherry-pick` the upstream commits onto the synced sub-repo HEAD and `git format-patch` the result.
For any newly-created `patches/<dir>/`, append to `patches/config.json` **preserving the compact one-line-per-entry style**:
{ "patch_dir": "src/electron/patches/<dir>", "repo": "src/third_party/<dir-or-nested-path>" }5. Validate with `e sync --3`
e sync --3 2>&1 | tee /tmp/bp_sync3.log
On `Patch failed at NNNN <subject>`:
- `cd` into the failing repo, inspect `git diff` for conflict markers.
- **Test-only files** (e.g. `web_tests/VirtualTestSuites`, `*_unittest.cc` context drift): take ours (`git checkout --ours -- <file>`) if the security-relevant hunks merged cleanly.
- **Substantive code conflicts**: a conflict is not a reason to drop. Work through, in order:
1. A merge of the same Change-Id on the **target milestone** (`git log --all --grep` on the Change-Id, or Gerrit `?q=change:<Change-Id>`) — swap to it. 2. The same Change-Id on a **nearby milestone** (the author's rebase, e.g. an `[M152]` CL when the target is M150 — status NEW is fine), and any **prerequisite CL** the fix was written against (the refactor that introduced the helpers or signatures the fix touches). Pick those so the fix applies verbatim; list prerequisites in the report. 3. Otherwise **hand-port** the fix's semantics onto the branch's code, inside the pick's patch file: resolve the hunks in the target repo, fold them into the pick's commit (`git commit --fixup` + autosquash rebase), then re-export. Keep the upstream commit header verbatim and append an `Electron adaptation notes (<branch>)` paragraph to th
Read more
name: chrome-release-verify description: End-to-end Chrome security backport for an Electron release branch. Given a Chrome Releases blog URL and a branch (e.g. 41-x-y), determines which CVE fixes are missing from the *actual synced source*, writes the cherry-pick patches locally, validates them with `e sync --3` + `lint --patches`, then pushes a single PR. Use when asked to backport a Chrome security release to N-x-y, "is CVE-X already in N-x-y?", or to produce/validate the cherry-pick set for a release branch.
Chrome Release → Validated Backport PR
Input: `$ARGUMENTS` = `<release-branch> <chrome-releases-blog-url>` (e.g. `41-x-y https://chromereleases.googleblog.com/2026/04/stable-channel-update-for-desktop_15.html`). Ask if either is missing.
The flow is **local-first**: nothing is pushed until every patch applies via `e sync --3` and passes `lint --patches`.
1. Map CVE → bug → fix CL
Run `/chrome-release-cls <blog-url>` (or its inline procedure) to produce `/tmp/cve_bugs.txt` (`CVE|bug|severity|desc`) and a per-bug canonical fix CL. For each CL also note `repo` (path under `src/`: `.`, `v8`, `third_party/{skia,angle,pdfium,dawn}`, `third_party/libaom/source/libaom`) and `gerrit-host`.
**Prefer the target-milestone merge CL** if one exists (e.g. on `41-x-y` ≈ M146, prefer the `[M146]` cherry-pick over the main CL) — it's already rebased and far less likely to conflict. Find it via `git log --all --grep` on the Change-Id, or Gerrit `?q=bug:<n>`. If Chrome did _not_ merge a fix to the target milestone, that is **not** by itself a reason to skip — Chrome's merge window is shorter than Electron's support window. Fall back to the main CL (or a nearby-milestone rebase, see step 5) and let step 3 decide whether the vulnerable code exists on the branch.
2. Prepare a synced worktree
Reuse `bp-<NN>` from `e show configs` if present, else `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
If sync fails with `NotADirectoryError: '<root>/src/.git/objects/info/alternates'`, remove `GIT_CACHE_PATH` from the bp config's `env` and retry.
3. Verify IN-TREE vs NEEDS-BACKPORT
For each bug, three checks against the **synced** repo:
1. `git -C "$repo" log HEAD --since='1 year ago' -E --grep="\b${bug}\b" --format='%h %s'` 2. Fetch Change-Id from Gerrit, then `git log HEAD --grep="^Change-Id: ${cid}$"` 3. `grep -rlE "(\b${bug}\b|${cid})" <root>/src/electron/patches/`
Any hit ⇒ IN-TREE. All empty ⇒ NEEDS-BACKPORT.
Rows that step 1 (or an upstream triage report you were handed) left as **RESTRICTED / no public CL** are not inherited — re-resolve them here before classifying. Run `git -C "$repo" fetch origin` and `git -C "$repo" log --all --remotes -E --grep="(Bug|Fixed):.*\b${bug}\b" --format='%h %s'`, the `chrome-release-cls` skill's `gitiles_grep` on `refs/heads/main` and the branch-heads refs of `chromium/src`, `v8` and the component's repo, and a fresh Gerrit `?q=bug:<id>` / `?q=message:<id>` query. The Gerrit change record is often restricted while the fix commit is already public in git, and restrictions lift during a run, so an earlier RESTRICTED verdict is a hint, not a result. A row stays RESTRICTED only when all of those are empty; it is never IN-TREE by omission — list it separately in the report so a human can follow up.
For each NEEDS-BACKPORT CL, also fetch its file list (`/changes/<proj>~<cl>/revisions/current/files`) and **skip** if every file is under `chrome/browser/`, `chrome/android/`, `ios/`, or `components/**/android/` — Electron doesn't compile those.
Report the table now (`CVE | Sev | Bug | Component | Verdict | CL`) and the proposed backport set; get user sign-off before continuing.
4. Write patches locally (no push yet)
For each backport CL, fetch the raw patch and write it into `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"For repos with no Gerrit host `e cherry-pick` supports (e.g. **libaom** on aomedia), instead `git cherry-pick` the upstream commits onto the synced sub-repo HEAD and `git format-patch` the result.
For any newly-created `patches/<dir>/`, append to `patches/config.json` **preserving the compact one-line-per-entry style**:
{ "patch_dir": "src/electron/patches/<dir>", "repo": "src/third_party/<dir-or-nested-path>" }5. Validate with `e sync --3`
e sync --3 2>&1 | tee /tmp/bp_sync3.log
On `Patch failed at NNNN <subject>`:
- `cd` into the failing repo, inspect `git diff` for conflict markers.
- **Test-only files** (e.g. `web_tests/VirtualTestSuites`, `*_unittest.cc` context drift): take ours (`git checkout --ours -- <file>`) if the security-relevant hunks merged cleanly.
- **Substantive code conflicts**: a conflict is not a reason to drop. Work through, in order:
1. A merge of the same Change-Id on the **target milestone** (`git log --all --grep` on the Change-Id, or Gerrit `?q=change:<Change-Id>`) — swap to it. 2. The same Change-Id on a **nearby milestone** (the author's rebase, e.g. an `[M152]` CL when the target is M150 — status NEW is fine), and any **prerequisite CL** the fix was written against (the refactor that introduced the helpers or signatures the fix touches). Pick those so the fix applies verbatim; list prerequisites in the report. 3. Otherwise **hand-port** the fix's semantics onto the branch's code, inside the pick's patch file: resolve the hunks in the target repo, fold them into the pick's commit (`git commit --fixup` + autosquash rebase), then re-export. Keep the upstream commit header verbatim and append an `Electron adaptation notes (<branch>)` paragraph to th
Other skills on electron.
More skills from other plugins.
migrate-radix-to-base
Migrates React projects and components from Radix UI to Base UI. Use when asked to migrate from radix, move to base-ui, convert…
taste-skill
tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of 247 curated gallery sites (One…
Questions about chrome-release-verify.
- Which coding agents can use chrome-release-verify?
- chrome-release-verify installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

