Jul 21, 2026·6 min read·15 visits
The @astrojs/netlify adapter fails to escape dots and other regular expression metacharacters in developer-defined image pathnames, generating insecure edge configurations that permit attackers to bypass path-level restrictions on Netlify's Image CDN.
A security vulnerability in @astrojs/netlify allows attackers to bypass remote image path restrictions by leveraging unescaped regular expression metacharacters. The integration adapter fails to sanitize developer-defined pathnames before interpolating them into a configuration JSON file consumed by Netlify's Edge Image CDN. This results in overly permissive matching behavior at the edge routing layer, enabling path-traversal and filter bypasses.
The @astrojs/netlify adapter is an integration for the Astro framework that enables building and deploying server-side rendered (SSR) applications directly onto Netlify. During the build phase, the adapter translates developer-defined remote image patterns (image.remotePatterns from astro.config.mjs) into a deployment configuration file located at .netlify/v1/config.json under the images.remote_images property.
This configuration acts as a whitelist of remote hosts and pathnames authorized to utilize Netlify's Edge Image Content Delivery Network (CDN) for caching and optimization. A vulnerability exists within versions of @astrojs/netlify prior to 8.1.2 where the adapter fails to escape regular expression metacharacters within literal pathnames during configuration translation.
The generated configurations are evaluated directly by Netlify's Image CDN at the edge. The absence of proper escaping results in an overly permissive matching pattern, enabling path-level authorization bypasses and allowing unauthorized image resources to be processed and cached.
The root cause of the vulnerability lies within the remotePatternToRegex() function inside the packages/integrations/netlify/src/index.ts file. When processing the configured pathnames, the logic attempts to construct regular expressions for exact matches or wildcard segments (such as /** or /*).
However, the implementation interpolates raw string variables from the developer configuration straight into the regular expression template without sanitizing special characters. Specifically, regular expression metacharacters like the dot (.) are interpreted by Netlify's edge routing engine as wildcards representing any character except a newline.
Since literal directory pathnames often contain dots (such as API version folders /v1.0/ or specific static files), this omission allows a dot to match alternative arbitrary characters (CWE-116, CWE-185). Additionally, there are no compensating runtime validation checks in place during edge CDN execution. Although Astro implements a strict exact-match verification utility named matchPattern() during standard SSR requests, this layer is completely bypassed when requests are served directly by Netlify's Edge Image CDN.
In vulnerable versions of @astrojs/netlify (prior to 8.1.2), the remotePatternToRegex translation block does not sanitize the input pathname before executing interpolation. The following code block demonstrates the vulnerable implementation:
if (pathname) {
if (pathname.endsWith('/**')) {
// Match any path.
regexStr += `(\\${pathname.replace('/**', '')}.*)`;
}
if (pathname.endsWith('/*')) {
// Match one level of path
regexStr += `(\\${pathname.replace('/*', '')}\\/[^/?#]+)\\/?`;
} else {
// Exact match
regexStr += `(\\${pathname})`;
}
}The patched version introduces an explicit escapeRegex utility function. This utility replaces all standard regex metacharacters, such as dots, asterisks, brackets, and parentheses, with their escaped counterparts before injecting them into the compiled regex. The fixed implementation is shown below:
/**
* Escape regex metacharacters in a literal string so it matches verbatim.
*/
function escapeRegex(literal: string): string {
return literal.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
// ... inside remotePatternToRegex() ...
if (pathname) {
if (pathname.endsWith('/**')) {
// Match any path. Escape the literal prefix so metacharacters
// (e.g. `.`) match verbatim instead of acting as wildcards.
regexStr += `(${escapeRegex(pathname.replace('/**', ''))}.*)`;
} else if (pathname.endsWith('/*')) {
// Match one level of path
regexStr += `(${escapeRegex(pathname.replace('/*', ''))}\\/[^/?#]+)\\/?`;
} else {
// Exact match
regexStr += `(${escapeRegex(pathname)})`;
}
}The fix is complete and robust because it maps all key special characters to safe literal representations. It preserves Astro's specific wildcard syntax (/** and /*) by parsing them first, and escaping only the static portion of the user-provided path. This prevents any secondary variant exploits against the path resolution mechanism.
Exploitation of this vulnerability requires a target application to deploy @astrojs/netlify with a remote image configuration containing dot characters in its pathname. Consider an astro.config.mjs setup whitelisting a specific versioned resource path:
// astro.config.mjs
image: {
remotePatterns: [{
protocol: 'https',
hostname: 'cdn.example.com',
pathname: '/img/v1.0/file',
}],
}When processed by a vulnerable adapter, this translates to the pattern https://cdn\\.example\\.com(:[0-9]+)?(\\/img/v1.0/file)([?][^#]*)?$ in .netlify/v1/config.json. Because the dot in v1.0 remains unescaped, an attacker can construct malicious requests to match alternative paths. For instance, the URL https://cdn.example.com/img/v1A0/file will be successfully matched as the dot evaluates 'A' as valid.
More critically, the unescaped dot matches a forward slash (/), allowing path traversal and directory crossing. An attacker requesting https://cdn.example.com/img/v1/0/file bypasses the intended directory restriction. This lets attackers load and optimize assets from unauthorized directories on the allowed host, manipulating the Edge Image CDN directly.
The security impact is classified as Low with a CVSS score of 3.7. The primary consequence is unauthorized resource consumption and filter bypass. Attackers can leverage the flawed regex to force Netlify's Edge Image CDN to retrieve, optimize, and cache arbitrary images from non-permitted paths on the target hostname.
While this does not lead directly to Remote Code Execution (RCE) or sensitive database disclosure, it enables attackers to hijack Netlify cloud resources (Resource Hijacking, MITRE ATT&CK T1496). This can lead to increased CDN operational bandwidth, unexpected serverless usage costs, and potential cache poisoning if malicious payloads are served via the optimized paths.
The vulnerability is not listed in the CISA KEV catalog, and there is no known active exploitation in the wild. Exploitation complexity is high because it requires specific target configurations containing metacharacter-adjacent structures on the whitelisted servers.
To remediate this vulnerability, developers must upgrade the @astrojs/netlify dependency to version 8.1.2 or higher. This updates the underlying configuration compiler to include the safe regex escaping mechanism.
Deployments can be verified by executing a local build via npm run build and auditing the output of .netlify/v1/config.json. Check the images.remote_images field to confirm that all dot characters in configured paths are escaped as \.. For example, a secure output should resemble (\\/img/v1\\.0\\/file) instead of (\\/img/v1.0/file).
If immediate dependency updates are not possible, developers should temporarily remove any regex metacharacters (including dots) from the pathname configurations in astro.config.mjs. Replacing file extensions or version strings with generic directory paths can mitigate direct path traversal risks.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@astrojs/netlify Astro | < 8.1.2 | 8.1.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-185: Incorrect Regular Expression / CWE-116: Improper Output Escaping |
| Attack Vector | Network |
| CVSS v3.1 Score | 3.7 (Low) |
| EPSS Score | Not Available |
| Impact | Filter Bypass / Resource Hijacking |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
The software does not properly escape metacharacters before incorporating user input into a regular expression, enabling unexpected matching behavior.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.
Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.