forked from dsh/panel-auth
fix: tolerate loopback Host behind reverse proxy, document Caddy setup
DSH pins privileged /api methods (settings.*, credentials.*, agentPreset.*, host.pickDirectory, ...) to loopback hosts by design. When a reverse proxy fronts the panel with the public Host header, those methods return 403. The supported deployment shape is forwarding Host as loopback upstream (header_up Host 127.0.0.1 in Caddy). This change: - skips the login origin check when the incoming Host is loopback (proxy context), while still rejecting real cross-site posts on public hosts; - documents the reverse-proxy requirement in the README; - extends tests with raw-request coverage for non-loopback cross-site rejection, port tolerance, and loopback-Host skip.
This commit is contained in:
@@ -439,6 +439,17 @@ function sameHost(originHeader, hostHeader) {
|
||||
}
|
||||
}
|
||||
|
||||
/** True when the Host header names the loopback authority (direct access or a
|
||||
* reverse proxy presenting a loopback Host upstream). */
|
||||
function isLoopbackHost(hostHeader) {
|
||||
try {
|
||||
const hostname = new URL(`http://${hostHeader}`).hostname.toLowerCase()
|
||||
return hostname === 'localhost' || hostname === '[::1]' || /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function readBody(req, maxBytes) {
|
||||
return new Promise((resolveBody) => {
|
||||
let size = 0
|
||||
@@ -521,6 +532,7 @@ export function installGuard(server, guard, { audit, loginPath, logoutPath, lock
|
||||
if (typeof origin === 'string' &&
|
||||
origin !== 'null' &&
|
||||
typeof host === 'string' &&
|
||||
!isLoopbackHost(host) &&
|
||||
!sameHost(origin, host)
|
||||
) {
|
||||
audit.write({
|
||||
|
||||
Reference in New Issue
Block a user