Every npm dependency in this repo is development tooling. There is no src/,
no block.json and no webpack config, so wp-scripts build compiles nothing;
node_modules, package.json and package-lock.json are all excluded from the
release zip by .distignore. Nothing here reaches production or a user — npm's
only real jobs in this project are husky + commitlint for the commit-message
hook.
That means these advisories carry no runtime risk. They are still worth closing:
the tooling runs on developer machines and in CI, and an empty npm audit is
what keeps the Dependabot queue from refilling with one PR per transitive
package (it previously held 22).
The overrides block in package.json exists because a handful of transitive
pins inside @wordpress/scripts block fixes that upstream has already shipped
elsewhere. @wordpress/[email protected] is already the latest release, so
there is no version to upgrade to, and npm audit fix moves nothing on its own
(it reports 32 → 32). npm's own suggestion to "fix" this by installing
@wordpress/[email protected] is a downgrade and is wrong.
Who maintains these
Renovate, not Dependabot. Renovate's npm manager treats overrides as a
first-class dependency type, so it opens PRs bumping these pins as upstream
releases land. Dependabot cannot: it bumps declared ranges and lockfile entries
only, with no mechanism to author or update an override — which is exactly why
this repo accumulated 22 open Dependabot PRs, one per transitive package, none of
which any declared dependency could reach. .github/dependabot.yml disables
Dependabot version updates for that reason and groups any future security
updates into a single PR.
Validation: .github/workflows/override-check.yml runs
bin/check-overrides.mjs weekly and on PRs touching package.json. It
re-resolves the tree without overrides and audits it — if an override's
package no longer audits as vulnerable, upstream shipped the fix and the job
fails to tell us to delete the override. Renovate keeps @wordpress/scripts
current, so upstream fixes arrive on their own; the check turns them into a
removal signal.
Active overrides
Six overrides clear all 32 advisories. Each fixes a whole cluster, so the list is deliberately shorter than the advisory count — pinning the leaves as well (an earlier draft pinned 20 packages) is redundant once the parent moves.
They are nested (parent-scoped) rather than global. "adm-zip": "^0.6.0" at
the top level would force that version everywhere in the tree; nesting it under
@wordpress/scripts changes only the path that actually needs it, so a future
dependency that legitimately wants a different major is unaffected. It also makes
each entry self-documenting — the parent named in package.json is the
blocking pin. Verified equivalent: both forms produce zero advisories and a
single copy of each package, with no duplicate left behind at a vulnerable
version.
| Override | Blocking pin | Clears | Remove when |
|---|---|---|---|
lighthouse → @sentry/node: ^10.70.0 | lighthouse pins @sentry/node@^9.28.1 | 16 entries: @sentry/node plus the whole @opentelemetry/* set (core, resources, sdk-trace-base, sql-common and 12 instrumentation-*). Sentry 9 pins the @opentelemetry/[email protected] line, which carries an unbounded-memory advisory fixed in otel 2.8 / Sentry ≥ 10.54. | lighthouse allows @sentry/node ≥ 10.54 |
lighthouse → puppeteer-core: ^25.8.0 | lighthouse pins puppeteer-core@^24.17.1 | puppeteer-core, @puppeteer/browsers, extract-zip, lighthouse | wp-scripts ships a puppeteer chain > 24.43.1 |
@wordpress/scripts → adm-zip: ^0.6.0 | @wordpress/scripts pins adm-zip@^0.5.9 | adm-zip (4 GB memory-allocation DoS, fixed in 0.6.0) | wp-scripts allows adm-zip ≥ 0.6.0 |
@wordpress/scripts → markdownlint-cli: ^0.49.1 | @wordpress/scripts pins markdownlint-cli@^0.31.1 (2022-era) | markdownlint-cli, markdownlint, markdown-it@12, linkify-it@3, minimatch | wp-scripts modernises its markdownlint-cli pin |
@wordpress/scripts → copy-webpack-plugin: ^14.0.0 | @wordpress/scripts pins copy-webpack-plugin@^10.2.0, which pins serialize-javascript@6 | copy-webpack-plugin, serialize-javascript (RCE via RegExp.flags + CPU-exhaustion DoS; all 6.x affected) | wp-scripts bumps copy-webpack-plugin to a major allowing serialize-javascript 7.x |
@wordpress/scripts → webpack-dev-server: ^6.0.0 | @wordpress/scripts pins webpack-dev-server@^5.2.1 (also reached via @pmmmwh/react-refresh-webpack-plugin, which npm dedupes to the overridden copy) | webpack-dev-server, sockjs, uuid@8 | wp-scripts moves to webpack-dev-server ≥ 6 |
Risk notes
The aggressive majors here (webpack-dev-server 5 → 6, copy-webpack-plugin
10 → 14, puppeteer-core 24 → 25, uuid 8 → 14 transitively) would be risky in
a project that actually ran the wp-scripts commands they back. This project runs
none of them:
webpack-dev-serveronly matters towp-scripts start, which has no source to serve here.copy-webpack-pluginandserialize-javascriptsit inside the webpack build, which compiles nothing —npm run buildexits 0 with "Source directory 'src' was not found".adm-zipbackswp-scripts plugin-zip; the release pipeline builds its zip withzip -rin.github/workflows/release-please.yml, not that command.puppeteer-core,lighthouseand the Sentry/otel chain back wp-scripts' e2e and performance testing. There are no e2e tests in this repo.markdownlint-clibackswp-scripts lint-md-docs, which is not wired up.
Verified after pinning: npm run build exits 0, and commitlint still accepts a
valid message and rejects an invalid one — the two things npm is actually load
bearing for here.
If the check fails
bin/check-overrides.mjs exits 1 with a ✖ STALE line naming the override.
Delete that entry from package.json, regenerate the lockfile
(npm install --package-lock-only), confirm npm audit still reports zero, and
update the table above.
One limitation to be aware of: the script strips all overrides at once before auditing, so it cannot tell that one override is redundant because a different override already fixes it transitively. That is how the earlier 20-entry list passed the check while six entries did the same job. When adding an override, check whether bumping the parent already covers it.