fix(relay-auth): close 5 pre-production security findings (F1–F5)
F1 (HIGH): bind step-up freshness to the required method (stepUpMethod) so a login-time or weaker (TOTP) factor can no longer satisfy a passkey requirement. F2 (HIGH): make the step-up gate host-driven and fail-closed on connect+reattach (deny when policy.required and the principal is missing/stale/wrong-method). F3 (MED): bind the WebAuthn assertion to the stored credential (credentialId cross-check + forward publicKey/credentialId to the verifier). F4 (LOW): make verifyDpopProof totally fail-safe (no unhandled throw), wrap the authz boundary into a clean audited 401, and validate cnfJkt format at issue. F5 (LOW): return newSignCount from finishAuthentication so the caller can persist the advanced counter (WebAuthn clone detection). All fixes ship regression tests. relay-auth: 122 tests green, tsc clean.
This commit is contained in:
@@ -124,10 +124,14 @@ export async function runEnforcement(
|
||||
await emitDeny(deps, ctx, base, 'too_many_sessions', now)
|
||||
return deny(403, 'too_many_sessions')
|
||||
}
|
||||
// 5. Step-up gate (Finding-3, v0.10) — only when a session principal is present.
|
||||
if (ctx.principal !== null) {
|
||||
const host = await deps.hosts.getById(outcome.hostId)
|
||||
if (host !== null && needsStepUp(ctx.principal, deps.stepUpPolicyFor(host), now)) {
|
||||
// 5. Step-up gate (Finding-3/F1/F2) — HOST-DRIVEN and FAIL-CLOSED on connect AND reattach.
|
||||
// When a host REQUIRES step-up, DENY unless an authenticated principal proves a FRESH step-up
|
||||
// of the required method. A missing host, a null principal, or a stale/wrong-method step-up all
|
||||
// fail closed. When the policy does not require step-up, this gate is a no-op.
|
||||
const host = await deps.hosts.getById(outcome.hostId)
|
||||
const policy = deps.stepUpPolicyFor(host as HostRecord)
|
||||
if (policy.required) {
|
||||
if (host === null || ctx.principal === null || needsStepUp(ctx.principal, policy, now)) {
|
||||
await emitDeny(deps, ctx, 'stepup', 'step_up_required', now)
|
||||
return deny(403, 'step_up_required')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user