const http = require("http"); const BASE_URL = "http://127.0.0.1:3000"; const ROUTES = [ "/", "/login", "/register", "/forgot-password", "/reset-password", "/privacy", "/terms", "/jobs", "/companies", "/api/health", "/api/jobs", "/api/companies", ]; const INJECTION_PAYLOADS = [ "' OR '1'='1", "", "\">", "../../../../etc/passwd", "%00", ]; function request(path, options = {}) { return new Promise((resolve, reject) => { const url = new URL(path, BASE_URL); const req = http.request(url, options, (res) => { let data = ""; res.on("data", (chunk) => (data += chunk)); res.on("end", () => resolve({ status: res.statusCode, headers: res.headers, body: data })); }); req.on("error", reject); if (options.body) { req.write(options.body); } req.end(); }); } async function runSecurityScan() { console.log("================================================="); console.log(" AUTOMATED OWASP DYNAMIC SECURITY AUDIT SCAN "); console.log("=================================================\n"); const findings = []; let testsCount = 0; // 1. Security Headers Audit console.log(">>> [1/4] Auditing Security Headers on Routes..."); for (const route of ROUTES) { testsCount++; try { const res = await request(route); const h = res.headers; if (!h["x-frame-options"]) { findings.push({ severity: "Medium", issue: "Missing X-Frame-Options header", target: route }); } if (!h["x-content-type-options"]) { findings.push({ severity: "Low", issue: "Missing X-Content-Type-Options header", target: route }); } if (!h["content-security-policy"]) { findings.push({ severity: "Medium", issue: "Missing Content-Security-Policy header", target: route }); } if (!h["strict-transport-security"]) { // HSTS is only required over HTTPS, flag as Info for HTTP findings.push({ severity: "Info", issue: "HSTS header absent over plain HTTP test listener", target: route }); } } catch (err) { findings.push({ severity: "High", issue: `Route request error: ${err.message}`, target: route }); } } console.log(` Checked ${ROUTES.length} routes for standard OWASP security headers.`); // 2. Reflected XSS & Injection on Query Parameters console.log(">>> [2/4] Testing Parameter Injection & Reflected XSS..."); for (const payload of INJECTION_PAYLOADS) { testsCount++; const testPath = `/jobs?search=${encodeURIComponent(payload)}&location=${encodeURIComponent(payload)}`; const res = await request(testPath); if (res.body.includes(payload) && !res.body.includes("<script>")) { // If raw unescaped script tag is in html body if (payload.includes("")) { findings.push({ severity: "High", issue: "Reflected XSS Vulnerability in search param", target: testPath }); } } if (res.status === 500) { findings.push({ severity: "High", issue: "Unhandled server exception on injection payload", target: testPath }); } } // 3. API Input Handling & Content-Type Sniffing console.log(">>> [3/4] Testing API Malformed Body Handling & Sensitive Disclosure..."); testsCount++; const badJsonRes = await request("/api/auth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: "{ malformed: json ", }); if (badJsonRes.status === 500) { findings.push({ severity: "Medium", issue: "Server 500 on malformed JSON body", target: "/api/auth/register" }); } // Check if stack traces leak into client response if (badJsonRes.body.includes("node_modules") || badJsonRes.body.includes("at Object.")) { findings.push({ severity: "High", issue: "Stack trace / internal path leaked in error response", target: "/api/auth/register" }); } // 4. Rate Limiting Probe on Auth Endpoints console.log(">>> [4/4] Verifying Rate Limit Abuse Prevention Protection..."); testsCount++; let rateLimitHit = false; for (let i = 0; i < 7; i++) { const r = await request("/api/auth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: `test${i}@spam.com`, password: "short" }), }); if (r.status === 429) { rateLimitHit = true; break; } } if (!rateLimitHit) { findings.push({ severity: "High", issue: "Rate limiter failed to block rapid registration requests", target: "/api/auth/register" }); } console.log("\n================================================="); console.log(` SCAN COMPLETE: ${testsCount} tests run`); console.log(` TOTAL FINDINGS: ${findings.length}`); console.log("=================================================\n"); console.log("RAW SECURITY FINDINGS TABLE:"); console.log(JSON.stringify(findings, null, 2)); if (findings.filter((f) => f.severity === "High").length > 0) { process.exit(1); } } runSecurityScan().catch((err) => { console.error("Scanner error:", err); process.exit(1); });