Changeset 5b1115b in Klonkt


Ignore:
Timestamp:
06/28/2026 11:48:20 AM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
89cc8c4
Parents:
4fdbbe6
Message:

fix(csrf): accept PUBLIC_BASE_URL host + X-Forwarded-Host in same-origin check

Behind a reverse proxy that doesn't preserve the Host (e.g. Apache .htaccess [P] proxying →
backend sees Host: localhost:3000), the same-origin CSRF check rejected every POST because it
compared Origin (the real domain) to the raw Host. Now it also accepts the operator-configured
PUBLIC_BASE_URL host and the proxy's X-Forwarded-Host — both operator/proxy-controlled, not
forgeable via a victim's browser. Makes Klonkt work behind common Apache/.htaccess setups.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/server.js

    r4fdbbe6 r5b1115b  
    250250  let originHost;
    251251  try { originHost = new URL(origin).host; } catch { return res.status(403).send('Ongeldige origin'); }
    252   if (originHost !== req.get('host')) return res.status(403).send('Cross-origin request geweigerd');
     252  // Behind a reverse proxy the raw Host is the backend bind (e.g. localhost:3000, when the
     253  // proxy doesn't preserve it — common with Apache .htaccess proxying), so also accept the
     254  // operator-configured PUBLIC_BASE_URL host and the proxy's X-Forwarded-Host. Both are
     255  // operator/proxy-controlled and can't be forged via a victim's browser, so this is safe.
     256  const allowedHosts = [req.get('host'), req.get('x-forwarded-host')];
     257  if (process.env.PUBLIC_BASE_URL) { try { allowedHosts.push(new URL(process.env.PUBLIC_BASE_URL).host); } catch { /* ignore bad config */ } }
     258  if (!allowedHosts.includes(originHost)) return res.status(403).send('Cross-origin request geweigerd');
    253259  next();
    254260});
Note: See TracChangeset for help on using the changeset viewer.