fix(door): never return raw controller reason to the client (D10)
Every door action bubbled the executor's reason/e.message to the client; redaction was password-literal + a fixed param-name regex, so a generic-adapter connection with a custom auth param + verbose upstream error could surface the secret client-side. Client returns are now a generic 'controller call failed' message; the redacted detail still goes to door_access_log for operators. redactDoorSecrets + callDoor gained an optional authParam (scrub the connection's actual auth param value regardless of name); threading conn.auth_param through the door-call selects is a deferred defense-in-depth follow-up (client leak is fully closed; native HeatSync e= is already regex-covered).
This commit is contained in:
@@ -18,6 +18,7 @@ export async function callDoor(opts: {
|
||||
url: string
|
||||
pinnedHost: string
|
||||
password?: string | null
|
||||
authParam?: string | null
|
||||
timeoutMs?: number
|
||||
}): Promise<DoorCallResult> {
|
||||
const guard = validateDoorTarget(opts.url, opts.pinnedHost)
|
||||
@@ -57,11 +58,11 @@ export async function callDoor(opts: {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
const snippet = redactDoorSecrets(received.slice(0, SNIPPET), opts.password)
|
||||
const snippet = redactDoorSecrets(received.slice(0, SNIPPET), opts.password, opts.authParam)
|
||||
return { ok: res.ok, status: res.status, snippet }
|
||||
} catch (e) {
|
||||
const msg = e instanceof Error ? e.message : 'request failed'
|
||||
return { ok: false, reason: redactDoorSecrets(msg, opts.password) }
|
||||
return { ok: false, reason: redactDoorSecrets(msg, opts.password, opts.authParam) }
|
||||
} finally {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user