UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

58 lines • 3.31 kB
/** * hosting/signin/browserGuard — the door guard a door whose credential rides * along on forged browser requests must have (design §3, H1/H4). * * Built from the HOST's own lists (one source: the same `allowedHosts` / * `allowedOrigins` the host is given). Refused at construction: * - `'any'` for either list — that says no browser reaches the door; * - `requireJsonContentType: false` — a form could post to it; * - no `allowedHosts` for a public URL that is not this machine; * - for a door that sets a cookie on a plain-http (development) public URL, a * LAN name in `allowedHosts` (a cookie without `Secure` must never be * offered to another machine); * - a public URL the lists themselves would refuse. * * Used by the sign-in door (its cookie) and by `proxy-token` (the proxy's * cookie or Windows login, turned into a header on every request it forwards). */ import { doorGuard, isLoopbackBind } from '../doorGuard.js'; import { SignInDoorConfigError } from './errors.js'; export function browserDoorGuard(name, lists, url, /** Does THIS door set a cookie without `Secure` (a plain-http development URL)? */ insecureCookie) { if (lists?.allowedHosts === 'any' || lists?.allowedOrigins === 'any') { throw new SignInDoorConfigError('guard', `allowedHosts/allowedOrigins 'any' says no browser reaches this door, and this door's ` + `credential rides along on every browser request. List the names people use`); } if (lists?.requireJsonContentType === false) { throw new SignInDoorConfigError('guard', `requireJsonContentType false would let a cross-site form post through this door`); } if (lists?.allowedHosts === undefined && !isLoopbackBind(url.hostname)) { throw new SignInDoorConfigError('guard', `the door hardening's allowedHosts is required (the same list the host uses): this door's ` + `credential rides along on every forged request, so the door must refuse other Host ` + `names and origins before identity is consulted`); } if (insecureCookie && Array.isArray(lists?.allowedHosts)) { const lan = lists.allowedHosts.filter((h) => !isLoopbackBind(h.replace(/:\d+$/, ''))); if (lan.length > 0) { throw new SignInDoorConfigError('guard', `a plain-http public URL serves a cookie without Secure, so allowedHosts may name only ` + `this machine (not ${lan.join(', ')}). https is required for any name other machines reach`); } } const guard = doorGuard({ name, ...(lists?.allowedHosts === undefined && { bindHost: url.hostname }), ...(lists?.allowedHosts !== undefined && { allowedHosts: lists.allowedHosts }), ...(lists?.allowedOrigins !== undefined && { allowedOrigins: lists.allowedOrigins }), }); const probe = guard.check({ method: 'POST', headers: { host: url.host, origin: url.origin, 'content-type': 'application/json' }, }); if (probe !== undefined) { throw new SignInDoorConfigError('guard', `the public URL ${url.origin} is refused by the door's own lists (${probe.code}). Add its ` + `host to allowedHosts (and its origin to allowedOrigins, when set)`); } return guard; } //# sourceMappingURL=browserGuard.js.map