You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Status: accepted risk, enforced by CI. No action is available or required.
Last verified 2026-08-29. The authoritative record is docs/SECURITY-AUDIT.md; this issue is
the discussion thread for it.
Summary
npm audit reports 10 high advisories on main, from two root packages
carrying three CVEs between them. Both roots are build-time-only
dependencies of the Netlify toolchain, and neither has a patched release in
existence — so there is nothing to upgrade to and nothing to fix.
The remaining eight audit entries are not distinct problems. They are chain
packages flagged solely for depending on a root.
first_patched_version: null on all three, confirmed against the GitHub
Advisory API. npm view confirms 2.0.2 and 2.0.1 are the newest published
versions of each package. Upstream fix tracked at netlify/framework-adapters#47.
That would roll back #106's major bumps and reintroduce the Astro 5
content-collection API — re-breaking the site in exactly the way #120 fixed. It
also would not clear the advisories, because the roots are unpatched at every
version.
This trap is guarded in two places: scripts/check-audit-baseline.sh keys on
GHSA IDs rather than npm's fixAvailable (which recommends the downgrade), and .github/dependabot.yml ignores @astrojs/netlify majors.
Why this is accepted
Both roots run at build time only. Neither is bundled into any deployed
function.
image-size processes only images committed to this repo. extract-zip is used
by local dev/functions tooling, not by anything in production. A DoS advisory
against a build-time parser fed exclusively repo-controlled input is not a
meaningful risk here; the realistic worst case is a local build hanging on a
malformed image the author added themselves.
Two caveats that are not part of the rationale, recorded because earlier
versions of this issue wrongly relied on them:
The site is not free of user input.netlify/functions/instagram-webhook.mts:88
fetches an attacker-supplied post.imageUrl and stores the bytes. It is
bearer-token gated (:44) and never parses the image, so it reaches no
parser — but "no user uploads" is false.
The site is not fully static.src/pages/blog/index.astro:7 sets export const prerender = false, and the built manifest carries six "prerender":false routes deployed at path: /*. SSR runs at request time.
Known gap: Astro vendors its own image-size
node_modules/astro/dist/assets/utils/vendor/image-size/ is a private copy that ships in the deployed SSR bundle. It is invisible to npm audit, not
covered by the overrides block, and not seen by check-audit-baseline.sh. Its
ICNS parser is logically identical to vulnerable upstream 2.0.2 — same missing
zero-length guard.
Not exploitable, failing closed twice:
astro.config.mjs declares no image: block, so domains and remotePatterns are empty and isRemoteAllowed returns false for every
remote URL — 403 before any fetch.
The configured service is @astrojs/netlify/image-service.js, whose exported service object has no transform method. The /_image endpoint's
first check is if (!("transform" in imageService)) throw — 500 before a
parser runs.
Both guards are configuration, not code. Adding a single image.domains
entry, or switching to a local/sharp image service, removes them and makes the
vendored parser reachable. Re-read this section before changing either.
What would change this
Either root publishes a patched release. check-audit-baseline.sh reports
this without failing, which is the cue to retire its baseline line.
@netlify/dev moves off them. @netlify/dev-utils@6.0.1 already dropped image-size, but forcing that chain via overrides pushes @netlify/vite-plugin onto an untested @netlify/dev major — the same shape
as the failure behind fix: restore content collections under Astro 7 glob loader #120, so it was deliberately not shipped.
A new advisory appears outside the accepted set. CI fails on that
automatically; triage it rather than assuming this acceptance covers it.
@astrojs/netlify 8.1.2 → 8.2.4 is available and compatible (peer astro: ^7.0.0 against the installed 7.1.6) but clears zero advisories — it
declares the same @netlify/vite-plugin: ^2.12.3, already resolving to 2.12.9.
Hygiene only, not a fix.
History
2026-08-18 — filed at 15 high advisories.
2026-08-21 — re-triaged; @netlify/dev-utils@6.0.1 override tested (10 → 5
findings) and deliberately not shipped.
Summary
npm auditreports 10 high advisories onmain, from two root packagescarrying three CVEs between them. Both roots are build-time-only
dependencies of the Netlify toolchain, and neither has a patched release in
existence — so there is nothing to upgrade to and nothing to fix.
The remaining eight audit entries are not distinct problems. They are chain
packages flagged solely for depending on a root.
image-size<=2.0.2image-size<=2.0.2extract-zip<=2.0.1first_patched_version: nullon all three, confirmed against the GitHubAdvisory API.
npm viewconfirms 2.0.2 and 2.0.1 are the newest publishedversions of each package. Upstream fix tracked at
netlify/framework-adapters#47.Chain-only entries:
@astrojs/netlify,@netlify/blobs,@netlify/dev,@netlify/dev-utils,@netlify/edge-functions-dev,@netlify/functions-dev,@netlify/redirects,@netlify/vite-plugin.npm audit fix --forcenpm proposes a downgrade of
@astrojs/netlifyfrom the installed 8.1.2 to6.4.1, flagged
isSemVerMajor: true, for 9 of the 10 findings:That would roll back #106's major bumps and reintroduce the Astro 5
content-collection API — re-breaking the site in exactly the way #120 fixed. It
also would not clear the advisories, because the roots are unpatched at every
version.
This trap is guarded in two places:
scripts/check-audit-baseline.shkeys onGHSA IDs rather than npm's
fixAvailable(which recommends the downgrade), and.github/dependabot.ymlignores@astrojs/netlifymajors.Why this is accepted
Both roots run at build time only. Neither is bundled into any deployed
function.
image-sizeprocesses only images committed to this repo.extract-zipis usedby local dev/functions tooling, not by anything in production. A DoS advisory
against a build-time parser fed exclusively repo-controlled input is not a
meaningful risk here; the realistic worst case is a local build hanging on a
malformed image the author added themselves.
Two caveats that are not part of the rationale, recorded because earlier
versions of this issue wrongly relied on them:
netlify/functions/instagram-webhook.mts:88fetches an attacker-supplied
post.imageUrland stores the bytes. It isbearer-token gated (
:44) and never parses the image, so it reaches noparser — but "no user uploads" is false.
src/pages/blog/index.astro:7setsexport const prerender = false, and the built manifest carries six"prerender":falseroutes deployed atpath: /*. SSR runs at request time.Known gap: Astro vendors its own
image-sizenode_modules/astro/dist/assets/utils/vendor/image-size/is a private copy thatships in the deployed SSR bundle. It is invisible to
npm audit, notcovered by the
overridesblock, and not seen bycheck-audit-baseline.sh. ItsICNS parser is logically identical to vulnerable upstream 2.0.2 — same missing
zero-length guard.
Not exploitable, failing closed twice:
astro.config.mjsdeclares noimage:block, sodomainsandremotePatternsare empty andisRemoteAllowedreturnsfalsefor everyremote URL — 403 before any fetch.
@astrojs/netlify/image-service.js, whose exportedserviceobject has notransformmethod. The/_imageendpoint'sfirst check is
if (!("transform" in imageService)) throw— 500 before aparser runs.
Both guards are configuration, not code. Adding a single
image.domainsentry, or switching to a local/sharp image service, removes them and makes the
vendored parser reachable. Re-read this section before changing either.
What would change this
check-audit-baseline.shreportsthis without failing, which is the cue to retire its baseline line.
@netlify/devmoves off them.@netlify/dev-utils@6.0.1already droppedimage-size, but forcing that chain viaoverridespushes@netlify/vite-pluginonto an untested@netlify/devmajor — the same shapeas the failure behind fix: restore content collections under Astro 7 glob loader #120, so it was deliberately not shipped.
automatically; triage it rather than assuming this acceptance covers it.
@astrojs/netlify8.1.2 → 8.2.4 is available and compatible (peerastro: ^7.0.0against the installed 7.1.6) but clears zero advisories — itdeclares the same
@netlify/vite-plugin: ^2.12.3, already resolving to 2.12.9.Hygiene only, not a fix.
History
@netlify/dev-utils@6.0.1override tested (10 → 5findings) and deliberately not shipped.
sharp,picomatch,nanoid,ipxand top-level
@netlify/blobscleared by fix: build CI with output assertions, Node pinning, and dependency triage #127 and the blobs 10 → 11 bump.Retired the stale
chain @netlify/imagesbaseline entry, corrected the twowrong premises above, and recorded the vendored-
image-sizegap (chore: re-triage the audit baseline, add npm to dependabot #144).Related: #106, #120, #127, #144