mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
81 lines
4.4 KiB
JavaScript
81 lines
4.4 KiB
JavaScript
/***********************************************************************************************************************************************************************
|
|
* File Name: originGuard.middleware.js
|
|
* Type of Program: Middleware
|
|
* Description: Two-layer server-side guard that blocks non-browser clients from reaching any API route.
|
|
*
|
|
* ── Layer 1 — Sec-Fetch-Site (ALL methods including GET) ────────────────────────────────────────
|
|
*
|
|
* Browsers (Chrome 76+, Firefox 90+, Safari 16.4+) automatically attach the Sec-Fetch-Site
|
|
* header on every request. It is a forbidden request header — JavaScript cannot set, override,
|
|
* or remove it. Its absence is a reliable, low-spoofability signal that the request originated
|
|
* from a tool rather than a real browser.
|
|
*
|
|
* Tools blocked by this layer (default configurations):
|
|
* ✓ Metasploit (Rex HTTP client) — no Sec-Fetch-Site
|
|
* ✓ BurpSuite Repeater / Scanner — no Sec-Fetch-Site
|
|
* ✓ Postman — no Sec-Fetch-Site
|
|
* ✓ curl / wget / httpie / python-requests — no Sec-Fetch-Site
|
|
* ✓ Nikto — no Sec-Fetch-Site
|
|
* ✓ sqlmap — no Sec-Fetch-Site
|
|
* ✓ dirb / gobuster / feroxbuster — no Sec-Fetch-Site
|
|
* ✓ nmap HTTP scripts — no Sec-Fetch-Site
|
|
*
|
|
* ── Layer 2 — Origin allowlist (POST / PUT / PATCH / DELETE only) ───────────────────────────────
|
|
*
|
|
* State-mutating requests must also carry an Origin header that matches ALLOWED_ORIGINS.
|
|
* Stops credential-stuffing and cross-origin mutation attempts from unlisted domains,
|
|
* even if an attacker managed to set Sec-Fetch-Site manually.
|
|
*
|
|
* ── What this does NOT stop ──────────────────────────────────────────────────────────────────────
|
|
*
|
|
* ✗ BurpSuite running as MITM proxy through a real browser session.
|
|
* The browser supplies all correct headers — requests are indistinguishable from
|
|
* legitimate traffic. The only defences here are rate limiting and valid credentials.
|
|
* ✗ A determined attacker who manually replicates all browser headers in their tool.
|
|
*
|
|
* ── Browser compatibility note ───────────────────────────────────────────────────────────────────
|
|
*
|
|
* Sec-Fetch-Site is supported by Chrome 76+ (Aug 2019), Firefox 90+ (Jul 2021),
|
|
* and Safari 16.4+ (Mar 2023). Requests from browsers older than these thresholds
|
|
* will be rejected. Given this is a modern SPA (Vite + React), this is acceptable.
|
|
*
|
|
* Author: Kenneth Obsequio (@lash0000)
|
|
* Date Created: Jun. 20, 2026
|
|
* Date Modified: Jun. 20, 2026
|
|
***********************************************************************************************************************************************************************/
|
|
"use strict";
|
|
|
|
const R = require('../utils/response.util');
|
|
|
|
const ALLOWED = (process.env.ALLOWED_ORIGINS || process.env.APP_URL || '')
|
|
.split(',')
|
|
.map(o => o.trim())
|
|
.filter(Boolean);
|
|
|
|
const MUTATION_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
|
|
|
|
module.exports = function originGuard(req, res, next) {
|
|
// Dev bypass: set ORIGIN_GUARD_DISABLED=true in .env to allow Postman/curl through.
|
|
// Hardcoded production lock — never bypassed even if the flag is accidentally set.
|
|
if (process.env.ORIGIN_GUARD_DISABLED === 'true' && process.env.NODE_ENV !== 'production') {
|
|
return next();
|
|
}
|
|
|
|
if (req.method === 'OPTIONS') return next(); // preflight — handled by cors()
|
|
|
|
// ── Layer 1: Sec-Fetch-Site must be present (covers GET scanning) ─────────
|
|
if (!req.headers['sec-fetch-site']) {
|
|
return R.error(res, 'Forbidden.', 403);
|
|
}
|
|
|
|
// ── Layer 2: Origin must be in allowlist for state-changing requests ──────
|
|
if (MUTATION_METHODS.has(req.method)) {
|
|
const origin = req.headers['origin'];
|
|
if (!origin || !ALLOWED.includes(origin)) {
|
|
return R.error(res, 'Forbidden.', 403);
|
|
}
|
|
}
|
|
|
|
next();
|
|
};
|