chore: ran security check for OWASP top 10
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
This commit is contained in:
77
api/tests/security-logging-monitoring-failures.test.ts
Normal file
77
api/tests/security-logging-monitoring-failures.test.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
import request from "supertest";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import { buildApp } from "../src/server";
|
||||
|
||||
let authApp: FastifyInstance;
|
||||
let csrfApp: FastifyInstance;
|
||||
const capturedEvents: Array<Record<string, unknown>> = [];
|
||||
|
||||
function attachSecurityEventCapture(app: FastifyInstance) {
|
||||
const logger = app.log as any;
|
||||
const originalChild = logger.child.bind(logger);
|
||||
logger.child = (...args: any[]) => {
|
||||
const child = originalChild(...args);
|
||||
const originalWarn = child.warn.bind(child);
|
||||
child.warn = (obj: unknown, ...rest: unknown[]) => {
|
||||
if (obj && typeof obj === "object") {
|
||||
const payload = obj as Record<string, unknown>;
|
||||
if (typeof payload.securityEvent === "string") capturedEvents.push(payload);
|
||||
}
|
||||
return originalWarn(obj, ...rest);
|
||||
};
|
||||
return child;
|
||||
};
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
authApp = await buildApp({ AUTH_DISABLED: false, SEED_DEFAULT_BUDGET: false });
|
||||
await authApp.ready();
|
||||
(authApp as any).ensureUser = async () => undefined;
|
||||
attachSecurityEventCapture(authApp);
|
||||
|
||||
csrfApp = await buildApp({ AUTH_DISABLED: true, SEED_DEFAULT_BUDGET: false });
|
||||
await csrfApp.ready();
|
||||
(csrfApp as any).ensureUser = async () => undefined;
|
||||
attachSecurityEventCapture(csrfApp);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (authApp) await authApp.close();
|
||||
if (csrfApp) await csrfApp.close();
|
||||
});
|
||||
|
||||
describe("A09 Security Logging and Monitoring Failures", () => {
|
||||
it("emits structured security log for unauthenticated protected-route access", async () => {
|
||||
capturedEvents.length = 0;
|
||||
|
||||
const res = await request(authApp.server).get("/dashboard");
|
||||
expect(res.status).toBe(401);
|
||||
|
||||
const event = capturedEvents.find((payload) => {
|
||||
return payload.securityEvent === "auth.unauthenticated_request";
|
||||
});
|
||||
expect(event).toBeTruthy();
|
||||
expect(event?.outcome).toBe("failure");
|
||||
expect(typeof event?.requestId).toBe("string");
|
||||
expect(typeof event?.ip).toBe("string");
|
||||
});
|
||||
|
||||
it("emits structured security log for csrf validation failures", async () => {
|
||||
capturedEvents.length = 0;
|
||||
|
||||
const res = await request(csrfApp.server)
|
||||
.post("/me")
|
||||
.set("x-user-id", `csrf-user-${Date.now()}`)
|
||||
.send({ displayName: "NoCsrf" });
|
||||
|
||||
expect(res.status).toBe(403);
|
||||
expect(res.body.code).toBe("CSRF");
|
||||
|
||||
const event = capturedEvents.find((payload) => payload.securityEvent === "csrf.validation");
|
||||
expect(event).toBeTruthy();
|
||||
expect(event?.outcome).toBe("failure");
|
||||
expect(typeof event?.requestId).toBe("string");
|
||||
expect(typeof event?.ip).toBe("string");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user