Listen to this Post
The @astrojs/netlify adapter converts Astro’s `image.remotePatterns` configuration into Netlify Image CDN’s `images.remote_images` regular expressions. However, the conversion logic produces regex patterns with broader semantics than Astro’s canonical matcher, allowing attackers to bypass the intended remote image restrictions.
How CVE-2026-33769 Works
The vulnerability stems from two distinct flaws in the Netlify adapter’s regex generation:
1. Hostname Wildcard Expansion: When a pattern like `.example.com` is provided, the adapter emits ([a-z0-9-]+\\.)?example\\.com, which makes the subdomain optional. Astro’s canonical `matchHostname()` helper requires exactly one subdomain and rejects the apex host. As a result, a request to `example.com` (without a subdomain) is accepted by Netlify Image CDN even though Astro’s own matcher would reject it.
2. Path Wildcard Unanchored Matching: For a pattern like /ok/, the adapter generates a segment regex but does not anchor the end of the URL. Netlify’s Image CDN treats `images.remote_images` entries as JavaScript regular expressions and calls .test(sourceImageUrl.href). This means a URL such as `/ok/a/b.svg` matches the `/ok/a` prefix, even though Astro’s `matchPathname()` helper rejects deeper paths.
The latest npm package `@astrojs/[email protected]` contains this conversion logic, and a minimal Astro build writes the broadened patterns into .netlify/v1/config.json. In Astro core versions 2.10.10 through 5.18.1, the `matchPathname()` function uses `.replace()` without anchoring for `/` patterns, allowing path traversal bypasses. The Netlify adapter exacerbates this by generating unanchored regexes that are even more permissive.
Reproduction Steps:
- Create an Astro app using `[email protected]` and
@astrojs/[email protected]. - Configure Netlify output and a restrictive pattern, e.g.,
remotePatterns: [{ protocol: 'http', hostname: '.localhost', pathname: '/ok/' }]. - Build the app; observe that `.netlify/v1/config.json` contains `http://([a-z0-9-]+\\.)?localhost(:[0-9]+)?(\\/ok/[^/?]+)/?([?][^])?`.
- Serve a canary SVG on
127.0.0.1:9001. - Request
/.netlify/images?url=http%3A%2F%2Flocalhost%3A9001%2Fok%2Fa.svg&w=100. Astro’s helper rejects the apex `localhost` for.localhost, but Netlify Image CDN accepts it and fetches the canary. - As a negative control, request `/.netlify/images?url=http%3A%2F%2Flocalhost%3A9001%2Fnope%2Fa.svg&w=100` – returns 403.
- Request `/.netlify/images?url=http%3A%2F%2Flocalhost%3A9001%2Fok%2Fa%2Fb.svg&w=100` – Astro’s `/ok/` helper rejects this deeper path, but Netlify Image CDN accepts it.
DailyCVE Form:
Platform: @astrojs/netlify
Version: 7.0.10
Vulnerability: Remote image allowlist bypass
Severity: Low (CVSS 2.9)
date: 2026-03-24Prediction: Patch expected in @astrojs/[email protected]
What Undercode Say:
Check affected versions npm list @astrojs/netlify Build the Astro app npm run build Inspect generated Netlify config cat .netlify/v1/config.json | grep -A5 "remote_images" Test hostname bypass (apex localhost) curl "http://localhost:4321/.netlify/images?url=http%3A%2F%2Flocalhost%3A9001%2Fok%2Fa.svg&w=100" Test path bypass (deeper path) curl "http://localhost:4321/.netlify/images?url=http%3A%2F%2Flocalhost%3A9001%2Fok%2Fa%2Fb.svg&w=100" Negative control (should return 403) curl "http://localhost:4321/.netlify/images?url=http%3A%2F%2Flocalhost%3A9001%2Fnope%2Fa.svg&w=100"
Exploit:
An attacker can craft requests to the Netlify Image CDN endpoint (
/.netlify/images) with a `url` parameter pointing to: - An apex domain (e.g.,
example.com) when the allowlist uses.example.com, bypassing the subdomain requirement. - A path that is a prefix of the allowed path (e.g., `/ok/a/b.svg` when the allowlist is
/ok/), bypassing the path segment restriction.
Both techniques cause the Netlify Image CDN to fetch and return image-like resources from unintended hosts or paths, effectively expanding the remote image fetch boundary beyond what the Astro configuration intended.Protection:
- Upgrade to a patched version of `@astrojs/netlify` once available (expected ≥7.0.11).
- As a temporary workaround, manually define `remote_images` in `netlify.toml` with properly anchored regular expressions that match Astro’s canonical `matchHostname()` and `matchPathname()` semantics:
- For
.example.com, require exactly one subdomain (e.g.,^[a-z0-9-]+\.example\.com$). - For
/ok/, anchor the full URL and match exactly one additional path segment (e.g.,^/ok/[^/?]+$). - Avoid using wildcard patterns in `remotePatterns` until the adapter is fixed; use explicit domain and path lists where possible.
Impact:
Any Astro app deployed with `@astrojs/netlify` and a restrictive `image.remotePatterns` config can expose a wider image-fetch boundary than intended. Public requests to the Netlify Image CDN endpoint can fetch URLs that Astro’s own matcher would reject, including apex hosts for `.host` patterns and deeper paths for `/path/` patterns. The practical impact depends on what the application intended to isolate behind the remote image allowlist, but it can disclose image-like resources from unintended hosts or paths behind the same configured remote origin family. This can lead to Server-Side Request Forgery (SSRF) against internal network services and cloud metadata endpoints.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

