Astro, Cache Poisoning, CVE-2026-41322 (Moderate)

Listen to this Post

How CVE-2026-41322 Works (Technical Details)

The vulnerability resides in Astro’s `@astrojs/node` adapter, specifically in the `serve-static.ts` file which handles static asset requests. When a request is made to a static JS/CSS file located under the `/_astro` path, and the request includes an incorrect or malformed `If-Match` header (e.g., If-Match: xxx), the expected behavior is to return a 412 Precondition Failed error. However, due to a flaw in the error-handling logic, the server responds with a 500 Internal Server Error and, critically, attaches a `Cache-Control: public, max-age=31536000, immutable` header—a one-year cache directive meant only for successful immutable file responses. This response is then cached by downstream CDNs (e.g., CloudFront, Cloudflare). Subsequent requests to the same asset, regardless of the `If-Match` header, will receive the cached 500 error page instead of the valid content until the cache expires, leading to application breakage.
From a code perspective, when the `send` module processes the file and encounters a precondition failure (ETag mismatch), it emits three events: `file` (setting forwardError = true), headers(setting the immutable cache header), and `error` (a 412 PreconditionFailedError). The error handler in `serve-static.ts` does not inspect the error’s status code; if `forwardError` is true, it always calls `res.writeHead(500)` and returns a generic 500 error.

DailyCVE Form

Platform: Astro / @astrojs/node
Version: 5.14.1 / 9.4.4
Vulnerability: Cache Poisoning
Severity: Moderate
Date: 2026-04-23

Prediction: 2026-04-20

What Undercode Say: Analytics

To reproduce and analyze the vulnerability, run the following commands to test a vulnerable endpoint directly.

1. Trigger the vulnerability using curl (target file may vary per site)
curl -s -o /dev/null -D - https://example.com/_astro/some-hashed-file.css -H "If-Match: xxx"
2. If the response contains a 500 status and the immutable cache header, the issue is confirmed
HTTP/1.1 500 Internal Server Error
Cache-Control: public, max-age=31536000, immutable
// 3. Example JS snippet to check for the vulnerable pattern in a response header
fetch('/_astro/vulnerable-asset.js')
.then(res => {
if (res.status === 500 && res.headers.get('Cache-Control')?.includes('immutable')) {
console.warn('CVE-2026-41322 pattern detected: Cache poisoning possible');
}
});
4. Mass-test a list of CSS/JS assets from the sitemap
find ./public/_astro -type f ( -name ".css" -o -name ".js" ) -exec curl -s -o /dev/null -D - {} -H "If-Match: xxx" \;

Exploit

An attacker can exploit this by sending a single malicious request to any immutable asset under the `/_astro` path with an invalid `If-Match` header. The poisoned response will be cached by intermediary reverse proxies or CDNs, effectively poisoning the cache for that specific asset for up to one year. When a legitimate user later requests the same asset, the cached 500 error is served instead of the intended content, breaking the page functionality. In a real-world scenario, the attacker would target a popular, known static resource to cause widespread disruption.

Protection from this CVE

  1. Upgrade Immediately: Update the `astro` package to version 5.14.2 or later, and `@astrojs/node` to version 9.4.5 or later, which fix the issue internally.
  2. Patch Manually (if upgrade is not possible): In serve-static.ts, modify the error handler to return the correct status code (412) and do not set the `Cache-Control` header on error responses.
  3. CDN Configuration: If using a CDN, configure the cache key to include the `If-Match` header, or disable caching for error responses (e.g., for CloudFront, set `Cache-Control: no-cache` on any origin returning 4xx/5xx).
  4. WAF Rule: Deploy a WAF rule to block requests containing a malformed `If-Match` header to static assets under /_astro.

Impact

Cache Poisoning — An attacker can force edge servers to cache an error page instead of the actual content, rendering one or more assets unavailable to legitimate users until the cache expires. This can lead to a partial Denial of Service (DoS) on static resources, breaking CSS styling and JavaScript functionality for all visitors routed through a poisoned CDN point of presence.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top