Fix security vulnerabilities

This commit is contained in:
2026-10-13 15:52:34 +01:00
parent 74103a19c9
commit eefb2ea5d2
46 changed files with 375 additions and 403 deletions
+2 -33
View File
@@ -1,14 +1,6 @@
import { describe, expect, test, beforeAll, afterAll } from "bun:test";
import path from "path";
import fs, { FSWatcher } from "fs";
import {
BundlerCTXMap,
BunextConfig,
GlobalHMRControllerObject,
PageFiles,
} from "../../types";
import { FileSystemRouter } from "bun";
import { BuildContext } from "esbuild";
import fs from "fs";
import grabDirNames from "../../utils/grab-dir-names";
import grabConstants from "../../utils/grab-constants";
@@ -25,29 +17,6 @@ let originalCwd = process.cwd();
let originalPort: string | undefined;
let startServer: (() => Promise<Bun.Server<any>>) | undefined;
declare global {
var BUNEXT_CONFIG: BunextConfig;
var BUNEXT_SERVER: Bun.Server<any> | undefined;
var BUNEXT_RECOMPILING: boolean;
var BUNEXT_WATCHER_TIMEOUT: any;
var BUNEXT_ROUTER: FileSystemRouter;
var BUNEXT_HMR_CONTROLLERS: GlobalHMRControllerObject[];
var BUNEXT_LAST_BUILD_TIME: number;
var BUNEXT_BUNDLER_CTX_MAP: { [k: string]: BundlerCTXMap } | undefined;
var BUNEXT_SSR_BUNDLER_CTX_MAP: { [k: string]: BundlerCTXMap };
var BUNEXT_BUNDLER_REBUILDS: 0;
var BUNEXT_PAGES_SRC_WATCHER: FSWatcher | undefined;
var BUNEXT_CURRENT_VERSION: string | undefined;
var BUNEXT_PAGE_FILES: PageFiles[];
var BUNEXT_ROOT_FILE_UPDATED: boolean;
var BUNEXT_SKIPPED_BROWSER_MODULES: Set<string>;
var BUNEXT_BUNDLER_CTX: BuildContext | undefined;
var BUNEXT_DIR_NAMES: ReturnType<typeof grabDirNames>;
var BUNEXT_CONSTANTS: ReturnType<typeof grabConstants>;
var BUNEXT_REACT_DOM_MODULE_CACHE: Map<string, any>;
var BUNEXT_REBUILD_RETRIES: number;
}
describe("E2E Integration", () => {
let server: any;
@@ -148,7 +117,7 @@ describe("E2E Integration", () => {
global.BUNEXT_CONSTANTS = undefined as any;
global.BUNEXT_SERVER = undefined;
global.BUNEXT_ROUTER = undefined as any;
global.BUNEXT_BUNDLER_CTX_MAP = undefined;
global.BUNEXT_BUNDLER_CTX_MAP = undefined as any;
global.BUNEXT_SSR_BUNDLER_CTX_MAP = undefined as any;
global.BUNEXT_HMR_CONTROLLERS = [];
global.BUNEXT_REACT_DOM_MODULE_CACHE = new Map<string, any>();
@@ -37,6 +37,8 @@ mock.module("../../../../src/functions/server/web-pages/handle-web-pages", () =>
default: async () => new Response("web-pages")
}));
const server = {} as Bun.Server<any>;
describe("bunext-req-handler", () => {
beforeEach(() => {
global.BUNEXT_CONSTANTS = {
@@ -61,7 +63,7 @@ describe("bunext-req-handler", () => {
test("middleware is caught", async () => {
const req = new Request("http://localhost/blocked");
const res = await bunextRequestHandler({ req });
const res = await bunextRequestHandler({ req, server });
expect(res.status).toBe(403);
expect(await res.text()).toBe("Blocked by middleware");
});
@@ -72,43 +74,43 @@ describe("bunext-req-handler", () => {
const req = new Request("http://localhost/__hmr", {
headers: { referer: "http://localhost/" }
});
const res = await bunextRequestHandler({ req });
const res = await bunextRequestHandler({ req, server });
expect(res.headers.get("Content-Type")).toBe("text/event-stream");
});
test("routes /api/ to handleRoutes", async () => {
const req = new Request("http://localhost/api/users");
const res = await bunextRequestHandler({ req });
const res = await bunextRequestHandler({ req, server });
expect(await res.text()).toBe("api-routes");
});
test("routes /public/ to handlePublic", async () => {
const req = new Request("http://localhost/public/image.png");
const res = await bunextRequestHandler({ req });
const res = await bunextRequestHandler({ req, server });
expect(await res.text()).toBe("public");
});
test("routes files like .js to handleFiles", async () => {
const req = new Request("http://localhost/script.js");
const res = await bunextRequestHandler({ req });
const res = await bunextRequestHandler({ req, server });
expect(await res.text()).toBe("files");
});
test("routes anything else to handleWebPages", async () => {
const req = new Request("http://localhost/about");
const res = await bunextRequestHandler({ req });
const res = await bunextRequestHandler({ req, server });
expect(await res.text()).toBe("web-pages");
});
test("excluded paths return 404", async () => {
const req = new Request("http://localhost/(group)/page");
const res = await bunextRequestHandler({ req });
const res = await bunextRequestHandler({ req, server });
expect(res.status).toBe(404);
});
test("routes using the request returned by middleware", async () => {
const req = new Request("http://localhost/rewrite-me");
const res = await bunextRequestHandler({ req });
const res = await bunextRequestHandler({ req, server });
expect(await res.text()).toBe("api-routes");
});
@@ -118,7 +120,7 @@ describe("bunext-req-handler", () => {
p === "/users/john.doe" ? { filePath: "/users/[id].tsx" } : null,
} as any;
const req = new Request("http://localhost/users/john.doe");
const res = await bunextRequestHandler({ req });
const res = await bunextRequestHandler({ req, server });
expect(await res.text()).toBe("web-pages");
});
});
@@ -8,10 +8,10 @@ import grabDirNames from "../../../../src/utils/grab-dir-names";
const { BUNX_TMP_DIR } = grabDirNames();
describe("grabPageBundledReactComponent", () => {
const originalConfig = global.CONFIG;
const originalConfig = (globalThis as any).CONFIG;
const fixtureDirs: string[] = [];
global.CONFIG = { development: true } as any;
(globalThis as any).CONFIG = { development: true } as any;
afterEach(() => {
for (const fixtureDir of fixtureDirs.splice(0)) {
@@ -19,12 +19,12 @@ describe("grabPageBundledReactComponent", () => {
fs.rmSync(fixtureDir, { recursive: true, force: true });
}
global.CONFIG = { development: true } as any;
(globalThis as any).CONFIG = { development: true } as any;
mock.restore();
});
afterAll(() => {
global.CONFIG = originalConfig;
(globalThis as any).CONFIG = originalConfig;
});
test("keeps __root context connected during SSR", async () => {
@@ -57,7 +57,7 @@ describe("grabPageBundledReactComponent", () => {
});
expect(result?.component).toBeDefined();
const html = renderToString(React.createElement(result!.component));
const html = renderToString(React.createElement(result!.component!));
expect(html).toContain("server-context");
});
});
@@ -1,5 +1,6 @@
import { afterEach, describe, expect, mock, test } from "bun:test";
import path from "path";
import type { GrabPageComponentRes } from "../../../types";
mock.module("../../../../src/utils/log", () => ({
log: {
@@ -42,7 +43,10 @@ describe("grabPageComponent", () => {
});
console.log("DEBUG-404:", res instanceof Response ? "Response" : JSON.stringify(res));
expect(res.serverRes?.response_options?.status).toBe(404);
expect(res).not.toBeInstanceOf(Response);
expect(
(res as GrabPageComponentRes).serverRes?.response_options?.status,
).toBe(404);
expect(log.error).not.toHaveBeenCalled();
});
});
+1 -1
View File
@@ -20,7 +20,7 @@ type Params = {
export default async function readRequestBody({
req,
max_bytes,
}: Params): Promise<Uint8Array | undefined> {
}: Params): Promise<Uint8Array<ArrayBuffer> | undefined> {
if (req.method == "GET" || req.method == "HEAD" || !req.body) {
return undefined;
}