fix(security): disable legacy XSS browser filter

This commit is contained in:
2026-11-09 15:56:30 +00:00
parent ff84e9ea0f
commit 63c56da143
3 changed files with 102 additions and 2 deletions
+1 -1
View File
@@ -63,7 +63,7 @@ export function middleware(request) {
);
// XSS protection (legacy)
response.headers.set("X-XSS-Protection", "1; mode=block");
response.headers.set("X-XSS-Protection", "0");
// Prevent MIME type sniffing
response.headers.set("X-Content-Type-Options", "nosniff");
+1 -1
View File
@@ -46,7 +46,7 @@ const securityHeaders = [
},
{
key: "X-XSS-Protection",
value: "1; mode=block"
value: "0"
}
// {
// key: "Content-Security-Policy",
+100
View File
@@ -0,0 +1,100 @@
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const vm = require("vm");
const rootDirectory = path.join(__dirname, "..", "..");
const toHeaderObject = (headers) =>
Object.fromEntries(headers.map(({ key, value }) => [key, value]));
const loadMiddleware = () => {
const middlewarePath = path.join(rootDirectory, "middleware.js");
const source = fs
.readFileSync(middlewarePath, "utf8")
.replace(
'import { NextResponse } from "next/server";',
'const { NextResponse } = require("next/server");'
)
.replace("export function middleware", "function middleware")
.concat("\nmodule.exports = { middleware };\n");
const context = {
Buffer,
Headers,
module: { exports: {} },
process: {
env: {
NEXTAUTH_URL: "https://example.test",
NODE_ENV: "production"
}
},
require: (moduleName) => {
assert.strictEqual(moduleName, "next/server");
return {
NextResponse: {
next: () => ({ headers: new Headers() })
}
};
},
crypto: {
randomUUID: () => "00000000-0000-4000-8000-000000000000"
}
};
vm.runInNewContext(source, context, { filename: middlewarePath });
return context.module.exports.middleware;
};
const run = async () => {
const nextConfig = require(path.join(rootDirectory, "next.config.js"));
const configuredRules = await nextConfig.headers();
const globalRule = configuredRules.find(
({ source }) => source === "/(.*)?"
);
assert.ok(globalRule, "Expected the global Next.js security-header rule");
assert.deepStrictEqual(toHeaderObject(globalRule.headers), {
"X-DNS-Prefetch-Control": "on",
"X-Frame-Options": "SAMEORIGIN",
"X-Content-Type-Options": "nosniff",
"X-Permitted-Cross-Domain-Policies": "none",
"Referrer-Policy": "origin-when-cross-origin",
"Strict-Transport-Security":
"max-age=63072000; includeSubDomains; preload",
"X-XSS-Protection": "0"
});
const middleware = loadMiddleware();
const response = middleware({ headers: new Headers() });
assert.strictEqual(response.headers.get("X-XSS-Protection"), "0");
assert.strictEqual(response.headers.get("X-Content-Type-Options"), "nosniff");
assert.strictEqual(response.headers.get("X-Frame-Options"), "DENY");
assert.strictEqual(
response.headers.get("Referrer-Policy"),
"strict-origin-when-cross-origin"
);
assert.strictEqual(
response.headers.get("Permissions-Policy"),
"geolocation=(), camera=(), microphone=(), fullscreen=(self)"
);
assert.strictEqual(
response.headers.get("Strict-Transport-Security"),
"max-age=63072000; includeSubDomains; preload"
);
assert.match(
response.headers.get("Content-Security-Policy"),
/default-src 'self'/
);
console.log("Security-header regression tests passed (2/2).");
};
if (require.main === module) {
run().catch((error) => {
console.error(error);
process.exit(1);
});
}
module.exports = run;