chore(deps): upgrade wxt to 0.21.2 and refresh security overrides - #141
Merged
Conversation
WXT 0.21 drops its bundled web-ext-run fork and takes web-ext, vite and typescript as peer dependencies instead, so vite joins devDependencies explicitly. web-ext and typescript were already direct devDependencies. Migration work the 0.21 breaking changes required: - The `wxt/testing` barrel export is gone. The fake browser and the Vitest plugin now come from `wxt/testing/fake-browser` and `wxt/testing/vitest-plugin`. - The generated .wxt/tsconfig.json enables verbatimModuleSyntax, noUncheckedIndexedAccess and noImplicitOverride. Kept those rather than reverting them through the prepare:tsconfig hook, which took 19 fixes: three type-only imports, two `override` modifiers, and guards where an array or record lookup genuinely can be undefined. FALLBACK_ADAPTER needs a non-null assertion because ADAPTERS is indexed by a computed expression; it is a non-empty const tuple, so the element always exists. - Sources zips are now `includeSources - excludeSources` and honour .gitignore, so stale dist/ and web-ext-artifacts/ output stops shipping to AMO. .gitignore did not cover CLAUDE.local.md (ignored globally, and symlinked into every worktree) or coverage/, which is now gitignored. Security overrides, re-checked against each alert and each parent's declared range: - yauzl has a patched release now, closing the advisory #137 had to leave open. Scoped to the 3.x line: only 3.2.0 is affected, and addons-linter separately pulls an unaffected 2.10.0. - shell-quote floor raised 1.8.5 -> 1.9.0. GHSA-395f-4hp3-45gv is patched in 1.9.0, so the old floor no longer covered the advisory it was for. - brace-expansion pinned per major (1.1.17 / 2.1.3 / 5.0.8). A single >=5.0.8 floor collapses every consumer onto v5, which minimatch v9 cannot call ("brace_expansion_1.default is not a function"), breaking `vitest run --coverage`. GHSA-mh99-v99m-4gvg is ignored via auditConfig because its single collapsed `<=5.0.7` range keeps matching the 1.x and 2.x backports; both tarballs were unpacked and confirmed to carry the EXPANSION_MAX_LENGTH fix. - yaml override dropped. It only ever arrived via web-ext-run, and nothing pulls it in now except vite's optional peer, which is not installed. svelte, svelte-check and @playwright/test picked up in-range releases. The majors left outstanding are the ones #137 deliberately held back (vite 8, @sveltejs/vite-plugin-svelte 7, vitest 4) plus jsdom, @types/node, prettier-plugin-svelte, typescript 7 and web-ext 10. Verified: 87 unit tests, a coverage run, svelte-check, prettier, web-ext lint (0 errors, same 5 warnings as dev), chrome and firefox builds, both zips, and `pnpm install --frozen-lockfile`. 0.21 raises the Node floor to 22, so the README prerequisite (which said 18+) is now wrong in the source package AMO reviewers build from, and package.json gained a matching `engines.node` so a wrong runtime fails fast instead of midway through the build. Reproducibility checked the way AMO checks it: extracting the sources zip into a clean directory and running install + zip:firefox there produces generated files that diff clean against the shipped build, all 14 file hashes equal. The zip containers differ by 36 bytes, which are the DOS timestamp fields in each entry header; the same is true of two back-to-back builds on 0.20, so it is not a regression here. The rest of the README was audited against the actual scripts while it was open: the Android example passed `--s`, which the flag parser does not accept (it takes `-s` or `--source-dir`); zip/test commands were not documented at all; and the web-ext.config.ts example used `startUrl`, which WXT does not read — the option is `startUrls`. `pnpm lint` was broken outright — it ran `pnpm build`, which emits chrome-mv3, and then linted .output/firefox-mv2, so on a clean checkout it failed with a missing-directory error. It builds firefox now.
The previous commit claimed WXT 0.21 honours .gitignore when building the sources zip. It does not. zip.mjs globs the filesystem with tinyglobby and never consults git; what actually filters is a hardcoded default list in resolve-config.mjs (node_modules, web-ext.config.ts, __tests__, *.test.* and .output) plus dot: false, which is why web-ext.config.ts and the dotfiles stay out and made the .gitignore theory look right. So being gitignored is not enough. Verified by creating coverage/, dist/ and web-ext-artifacts/ and running `pnpm zip:firefox`: all three landed in royalrefresh-1.8.0-sources.zip. `vitest --coverage` and `web-ext build` each leave one of these behind, so shipping them to AMO only takes running the wrong command before zipping. This is not hypothetical — the sources zip built before this fix carried modules/wsl-browser.ts, an untracked machine-local file. Adds the three globs back and rewrites the comment, which also wrongly said dist/ and web-ext-artifacts/ used to be listed here. They never were, so as written it invited the next maintainer to delete the entries again.
engines.node was added so a wrong runtime fails fast rather than midway through a build, but pnpm treats it as advisory by default: with a >=99 floor, pnpm 11.7.0 prints "[WARN] Unsupported engine" and still exits 0. engineStrict turns that into a hard error at install time. Node 24 on CI and the >=22 floor are unaffected, and the lockfile does not change. Also notes that the GHSA-mh99-v99m-4gvg ignore is unconditional while the overrides backing it only cover majors 1, 2 and 5. That is every brace-expansion in the tree today, but a fourth major arriving via a new dependency would get no floor and no audit signal either.
AMO reviewers rebuild the add-on from the sources zip, so the archive has to install and build on its own and produce the extension we shipped. That check was being done by hand. This scripts it: unpack the archive into a temp directory, run `pnpm install --frozen-lockfile && pnpm zip:firefox` there, then compare the SHA-256 of every file in the resulting extension against the shipped one. Currently 14/14 match. Missing and extra files are reported alongside hash mismatches, and it exits non-zero on any of them. The work directory is kept whenever anything fails, so a broken install or build leaves its logs behind; --keep holds on to it after a passing run too. Needs unzip on PATH. Zip containers can differ by a few dozen bytes with every file identical, because each entry header carries a DOS timestamp — two back-to-back builds of the same source differ the same way. Only file hashes are compared; the container sizes are printed for context.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Upgrades WXT
0.20.27 -> 0.21.2and re-checks everypnpmsecurity override againstits advisory and its parent's declared range.
pnpm auditstays clean.WXT 0.21 drops its bundled
web-ext-runfork and takes web-ext, vite and typescript aspeer dependencies instead, so
vitejoinsdevDependenciesexplicitly. Most of thisdiff follows from that one change. No runtime dependency changed —
dompurifyis stillthe only thing that ships in the bundle, and it is untouched.
Migration
wxt/testingbarrel is gone — nowwxt/testing/fake-browserandwxt/testing/vitest-plugin.verbatimModuleSyntax,noUncheckedIndexedAccess,noImplicitOverride), kept rather than reverted throughprepare:tsconfig. 19 fixes:three type-only imports, two
overridemodifiers, and guards where a lookup genuinelycan be
undefined.FALLBACK_ADAPTERneeds a non-null assertion becauseADAPTERSisindexed by a computed expression; it is a non-empty
consttuple, so the elementalways exists.
package.jsongainedengines.node, plusengineStrict: true— on its own pnpm treatsenginesas advisory and exits 0. TheREADME prerequisite (which said 18+) is corrected; it was wrong in the source package
AMO reviewers build from.
Security overrides
yauzl@3>=3.2.1— patched release exists now, closing the advisory #137 had to leave open. Scoped to 3.x: only 3.2.0 is affected, and addons-linter separately pulls an unaffected 2.10.0.shell-quote1.8.5 -> 1.9.0— GHSA-395f-4hp3-45gv is patched in 1.9.0, so the old floor no longer covered the advisory it was added for.brace-expansion1.1.17/2.1.3/5.0.8) — see below.yamlweb-ext-run.The one thing worth reviewing. A single
>=5.0.8floor collapses every consumer ontov5, which minimatch v9 cannot call (
brace_expansion_1.default is not a function) —that breaks
vitest run --coverage. Three majors are in the tree at once (minimatch v3wants
^1, v9 wants^2, v10 wants^5), so each line gets its own floor.GHSA-mh99-v99m-4gvg then keeps matching, because it declares one collapsed
<=5.0.7range spanning every major. Both tarballs were unpacked and checked: 1.1.16/2.1.2 have
no
EXPANSION_MAX_LENGTH, 1.1.17/2.1.3 do. It is an artefact of the advisory's metadata,not real exposure, so it is ignored via
auditConfig.minimumReleaseAgeExcludeexempts two versions published inside pnpm's defaultrelease-age window; safe to delete once they age out.
Sources zip
WXT 0.21 computes the sources archive as
includeSources - excludeSources, globbed offthe filesystem —
.gitignoreis not consulted. Gitignored build output thereforeships to AMO whenever it exists at zip time; verified by creating
coverage/,dist/and
web-ext-artifacts/and zipping. All three are now excluded explicitly, along withCLAUDE.local.md(a machine-local symlink ignored only via~/.gitignore_global).New
pnpm verify:sourcesscripts the AMO reproducibility check that was being done byhand: unpack the archive,
install --frozen-lockfile && zip:firefoxinside it, thencompare the SHA-256 of every file against the shipped extension. Currently 14/14 match.
Zip containers still differ by a few dozen bytes — DOS timestamps in the entry headers,
which two back-to-back builds differ by as well.
Also fixed
pnpm lintwas broken outright. It ranpnpm build, which emitschrome-mv3, thenlinted
.output/firefox-mv2— so on a clean checkout it failed with a missing-directoryerror. It builds firefox now.
--s, whichthe flag parser does not accept; the
web-ext.config.tsexample usedstartUrlwhereWXT's option is
startUrls; and the zip/test commands were undocumented.Testing
pnpm buildpnpm build:firefox,pnpm zip:firefox,pnpm verify:sources(14/14 files match)--coveragerun;pnpm check0 errors;pnpm lint0 errors andthe same 5 pre-existing
innerHTMLwarnings asdev;format:check;install --frozen-lockfileNot included
Majors held back on purpose: the ones #137 deferred (vite 8,
@sveltejs/vite-plugin-svelte7, vitest 4) plus jsdom,
@types/node,prettier-plugin-svelte, typescript 7 andweb-ext 10.
Follows #137, which left the
yauzladvisory open pending an upstream release.