fix(security): disable legacy XSS browser filter
This commit is contained in:
@@ -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;
|
||||
Reference in New Issue
Block a user