CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-hp3v-mfqw-h74c: @astrojs/netlify generates an overly-broad Netlify Image CDN allowlist because remotePatterns.pathname metacharacters are not escaped

lowCVSS 3.7
Summary The @astrojs/netlify adapter converts each image.remotePatterns entry into a regular expression that is written to .netlify/v1/config.json under images.remote_images. Netlify's Image CDN uses these regexes as the allowlist that decides which remote image URLs it will optimize. remotePatternToRegex() escapes . in the hostname but interpolates the literal pathname into the regex without escaping regex metacharacters. As a result, the generated allowlist is broader than the pattern the developer declared, and broader than Astro's canonical matchPattern() helper (which compares non-wildcard pathnames by exact string equality). This is a residual of the same bug class addressed in CVE-2026-54300 (PR #17018, commit 1310277d). That fix corrected wildcard semantics and added a $ anchor but did not add metacharacter escaping for literal pathnames. Details In packages/integrations/netlify/src/index.ts, remotePatternToRegex() escapes dots in the hostname: regexStr += hostname.replace(/\./g, '\\.'); but interpolates the pathname unescaped in all three branches, e.g. the exact-match branch: regexStr += (\\${pathname}); Any regex metacharacter in the literal path (., +, ?, (, [, ...) is therefore passed through raw. Because . matches any character (including /), a restrictive pattern is silently widened. The security boundary on Netlify is the generated regex itself — Netlify's Image CDN enforces it directly and Astro's runtime matchPattern() is not in the loop for this path, so there is no compensating layer that re-validates the request. Proof of Concept Configure an SSR site with a literal pathname containing a .: // astro.config.mjs image: { remotePatterns: [{ protocol: 'https', hostname: 'cdn.example.com', pathname: '/img/v1.0/file', }], } Run astro build and inspect .netlify/v1/config.json images.remote_images[0]: https://cdn\.example\.com(:[0-9]+)?(\/img/v1.0/file)([?][^#]*)?$ Testing the generated regex: - https://cdn.example.com/img/v1.0/file -> M

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
low — CVSS 3.7
Published
2026-07-20
Last updated
2026-07-20
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-hp3v-mfqw-h74c

More from GitHub Security Advisories