mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 22:49:41 +02:00
fix(deps): clear production npm advisories, fix sw.js caching regression
Resolves the four advisories that reach the production dependency tree. The other 16 npm audit reports are devDependencies-only (Remotion, Puppeteer, postcss, the eslint/tsx toolchain) and never ship to users. - @fastify/static 9.1.3 -> 10.1.3 GHSA-8pvw-jcv7-9cmj (authz bypass via non-canonical URL paths). Covers <=10.1.1, so all of 9.x is affected and the fix exists only on the 10.x line. - find-my-way 9.6.0 -> 9.8.0 GHSA-c96f-x56v-gq3h (HTTP/2 DDoS) - fast-uri 3.1.2 -> 3.1.5 GHSA-v2hh-gcrm-f6hx (host confusion) - brace-expansion -> 5.0.9/1.1.18 GHSA-3jxr-9vmj-r5cp (expansion DoS) The last three are transitive and needed only a lockfile re-resolve, so no overrides were introduced. The @fastify/static major changes setHeaders' first argument from a Node ServerResponse to a FastifyReply. Two consequences: 1. res.setHeader() -> reply.header(). The v9 body throws TypeError from inside the plugin on every static request. 2. Precedence flips, silently. The callback used to write to the raw response and lose to the route's staged reply headers; it now writes to the reply and wins. That gave /sw.js a year of immutable in place of the no-cache, no-store its route sets, pinning a service worker on every client with no server-side recovery. A route that already set Cache-Control now keeps it. Verified against v9 to confirm the sw.js behaviour is a regression and not a pre-existing bug. ws appears in npm audit but production is on 8.21.0, outside the vulnerable range; the only affected copy is bundled under @remotion/renderer (dev-only, and remotion is pinned at 4.0.473 because the compositor refuses to start on a version mismatch). Adds test/static-cache-headers.test.ts, which drives a real server and covers a caching contract that had no test at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+16
-4
@@ -781,19 +781,31 @@ export class WebServer extends EventEmitter {
|
||||
|
||||
// Serve static files — content-hashed assets (e.g. app.a3f8c2e1.js) are immutable, cache aggressively.
|
||||
// HTML must revalidate every time so browsers pick up new hashed filenames after deploys.
|
||||
// cacheControl disabled so setHeaders has full control (fastify-static's reply.headers() overwrites setHeaders otherwise).
|
||||
// cacheControl disabled so setHeaders owns Cache-Control for plain static assets.
|
||||
// preCompressed: serve pre-built .br/.gz files (from build step) to avoid per-request CPU compression
|
||||
await this.app.register(fastifyStatic, {
|
||||
root: join(__dirname, 'public'),
|
||||
prefix: '/',
|
||||
cacheControl: false,
|
||||
preCompressed: true,
|
||||
setHeaders: (res, path) => {
|
||||
// ⚠️ @fastify/static v10 changed this callback's first argument from a Node
|
||||
// `ServerResponse` to a `FastifyReply`, so it is `reply.header()` here and
|
||||
// NOT `res.setHeader()`. A v9-style body throws TypeError on every static
|
||||
// request, which is every page load. See the v10.0.0 release notes.
|
||||
setHeaders: (reply, path) => {
|
||||
// ⚠️ That same change ALSO flipped precedence, and silently. Under v9 this
|
||||
// callback wrote to the raw response and Fastify's staged reply headers then
|
||||
// overwrote it, so a route that set its own Cache-Control before .sendFile()
|
||||
// won. Under v10 the callback writes to the reply itself and now wins instead,
|
||||
// which handed `/sw.js` a year of `immutable` in place of the `no-cache,
|
||||
// no-store` its route asks for — a service worker that can never update.
|
||||
// So: a route that already decided keeps its answer.
|
||||
if (reply.getHeader('Cache-Control') !== undefined) return;
|
||||
// Use .includes() not .endsWith() — preCompressed serves .html.br/.html.gz
|
||||
if (path.includes('.html')) {
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
reply.header('Cache-Control', 'no-cache');
|
||||
} else {
|
||||
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
|
||||
reply.header('Cache-Control', 'public, max-age=31536000, immutable');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user