fix: treat Origin: null as absent instead of rejecting login
The audit diagnostics showed the real browser posting the login form with Origin: null (opaque context — sandboxed iframe, privacy proxy, or browser isolation product), which is not an attack signal. Skip the origin check for the literal "null" value; real cross-site posts with a concrete foreign origin are still rejected. Tests: Origin:null POST tolerated, foreign origin still 403.
This commit is contained in:
@@ -451,11 +451,19 @@ export function installGuard(server, guard, { audit, loginPath, logoutPath }) {
|
||||
// Cross-origin form posts are rejected: the login form must come from this host.
|
||||
// Hostname-level comparison tolerates port/case differences that proxies
|
||||
// or alternate listeners introduce, while still blocking foreign sites.
|
||||
// `Origin: null` (opaque contexts: sandboxed iframes, privacy proxies,
|
||||
// browser isolation) carries no usable origin information — treat it like
|
||||
// an absent header instead of rejecting real users.
|
||||
const origin = req.headers.origin
|
||||
const host = req.headers.host
|
||||
const ip = clientIp(req)
|
||||
const ua = req.headers['user-agent'] ?? ''
|
||||
if (typeof origin === 'string' && typeof host === 'string' && !sameHost(origin, host)) {
|
||||
if (
|
||||
typeof origin === 'string' &&
|
||||
origin !== 'null' &&
|
||||
typeof host === 'string' &&
|
||||
!sameHost(origin, host)
|
||||
) {
|
||||
audit.write({
|
||||
event: 'login-fail',
|
||||
username: '',
|
||||
|
||||
@@ -94,6 +94,10 @@ assert.match(await r.text(), /非法请求来源/)
|
||||
r = await post('/panel-auth/login', 'username=admin&password=s3cret-pass&next=%2F', { Origin: 'http://127.0.0.1:9999' })
|
||||
assert.equal(r.status, 303)
|
||||
|
||||
// 5d. `Origin: null` (opaque context: privacy proxy / sandboxed iframe) → tolerated
|
||||
r = await post('/panel-auth/login', 'username=admin&password=s3cret-pass&next=%2F', { Origin: 'null' })
|
||||
assert.equal(r.status, 303)
|
||||
|
||||
// 6. POST login with correct credentials → 303 + cookie + next
|
||||
r = await post('/panel-auth/login', 'username=admin&password=s3cret-pass&next=%2Fsome%2Fpage')
|
||||
assert.equal(r.status, 303)
|
||||
|
||||
Reference in New Issue
Block a user