Files
EpicNext-Cms/src/lib/ddos.ts
T
openhands fd4d0fa1cb
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Successful in 30s
CI / tests-unit (push) Successful in 1m39s
CI / tests-integration (push) Successful in 1m42s
CI / tests-ui (push) Successful in 2m27s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m0s
feat(security): harden anti-DDoS gate with scanner triage, tiered blocks and in-process global halt
2026-09-22 21:57:09 +02:00

55 lines
1.3 KiB
TypeScript

export type DdosCategory = "pages" | "api" | "auth";
export function classifyDdos(pathname: string): DdosCategory {
if (
pathname === "/api/auth" ||
pathname.startsWith("/api/auth/") ||
pathname === "/login" ||
pathname.startsWith("/login/") ||
pathname === "/register" ||
pathname.startsWith("/register/") ||
pathname === "/admin" ||
pathname.startsWith("/admin/")
) {
return "auth";
}
if (pathname.startsWith("/api/")) return "api";
return "pages";
}
const HOSTILE_PATH_SEGMENTS = new Set([
"wp-admin",
"wp-login.php",
"wp-includes",
"phpmyadmin",
"pma",
"adminer",
"server-status",
".env",
".git",
]);
const HOSTILE_PATH_EXTENSIONS = [".php", ".asp", ".aspx", ".jsp", ".cgi"];
/**
* Cheap scanner/exploit triage. These paths are never routes in this app, so a
* hit is almost certainly an automated attack sweep; dropping it here costs no
* Redis work and never affects genuine traffic.
*/
export function isSuspiciousPath(pathname: string): boolean {
const lower = pathname.toLowerCase();
for (const segment of lower.split("/")) {
if (HOSTILE_PATH_SEGMENTS.has(segment)) return true;
}
for (const extension of HOSTILE_PATH_EXTENSIONS) {
if (
lower.endsWith(extension) ||
lower.includes(`${extension}/`) ||
lower.includes(`${extension}?`)
) {
return true;
}
}
return false;
}