mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
middleware do not prohibits
Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
@@ -76,6 +76,13 @@ const ALLOWED = (process.env.ALLOWED_ORIGINS || process.env.APP_URL || '')
|
|||||||
|
|
||||||
const MUTATION_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
|
const MUTATION_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
|
||||||
|
|
||||||
|
// Routes that legitimately receive a top-level cross-site navigation — a third-party
|
||||||
|
// IdP (Google) redirects the browser here after consent, so Sec-Fetch-Site is
|
||||||
|
// correctly "cross-site" even though the request is a real browser, not an attacker.
|
||||||
|
// Still gated on GET + navigate|document below, so this doesn't open the route to
|
||||||
|
// cross-site fetch()/XHR — only actual browser navigations.
|
||||||
|
const CROSS_SITE_NAVIGATION_PATHS = new Set(['/google/callback']);
|
||||||
|
|
||||||
// Valid Sec-Fetch-Mode + Sec-Fetch-Dest combinations expected on this API server.
|
// Valid Sec-Fetch-Mode + Sec-Fetch-Dest combinations expected on this API server.
|
||||||
const VALID_FETCH_COMBOS = new Set([
|
const VALID_FETCH_COMBOS = new Set([
|
||||||
'cors|empty', // standard fetch() from cross-origin SPA
|
'cors|empty', // standard fetch() from cross-origin SPA
|
||||||
@@ -93,8 +100,12 @@ module.exports = function originGuard(req, res, next) {
|
|||||||
if (req.method === 'OPTIONS') return next(); // preflight — handled by cors()
|
if (req.method === 'OPTIONS') return next(); // preflight — handled by cors()
|
||||||
|
|
||||||
// ── Layer 1a: Sec-Fetch-Site must be present and not cross-site ───────────
|
// ── Layer 1a: Sec-Fetch-Site must be present and not cross-site ───────────
|
||||||
|
// Exception: OAuth callback routes receive a real cross-site top-level navigation
|
||||||
|
// from the IdP's domain — allowed only in combination with the navigate|document
|
||||||
|
// check in Layer 1b, so cross-site fetch()/XHR is still rejected everywhere.
|
||||||
const fetchSite = req.headers['sec-fetch-site'];
|
const fetchSite = req.headers['sec-fetch-site'];
|
||||||
if (!fetchSite || fetchSite === 'cross-site') {
|
const isCrossSiteNavigationRoute = req.method === 'GET' && CROSS_SITE_NAVIGATION_PATHS.has(req.path);
|
||||||
|
if (!fetchSite || (fetchSite === 'cross-site' && !isCrossSiteNavigationRoute)) {
|
||||||
return R.error(res, 'Forbidden.', 403);
|
return R.error(res, 'Forbidden.', 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +115,9 @@ module.exports = function originGuard(req, res, next) {
|
|||||||
if (!fetchMode || !fetchDest || !VALID_FETCH_COMBOS.has(`${fetchMode}|${fetchDest}`)) {
|
if (!fetchMode || !fetchDest || !VALID_FETCH_COMBOS.has(`${fetchMode}|${fetchDest}`)) {
|
||||||
return R.error(res, 'Forbidden.', 403);
|
return R.error(res, 'Forbidden.', 403);
|
||||||
}
|
}
|
||||||
|
if (isCrossSiteNavigationRoute && `${fetchMode}|${fetchDest}` !== 'navigate|document') {
|
||||||
|
return R.error(res, 'Forbidden.', 403);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Layer 2: At least one browser-native fingerprint header must be present ─
|
// ── Layer 2: At least one browser-native fingerprint header must be present ─
|
||||||
if (!req.headers['sec-ch-ua'] && !req.headers['accept-language']) {
|
if (!req.headers['sec-ch-ua'] && !req.headers['accept-language']) {
|
||||||
|
|||||||
Reference in New Issue
Block a user