2.3 KiB
privacy/assert-no-leak.ts
(no submodules)
Purpose
assertNoLeak is the runtime sentinel that scans an outgoing Request
URL and body byte-by-byte for three classes of forbidden content: the
full SHA-1 digest of the password being checked, the password itself,
and the configured email. A hit on any of the three throws
HibpError(HIBP.MALFORMED_RESPONSE) carrying a leakClass tag that
identifies what was leaked — without ever echoing the leaked bytes into
the error message.
Features
- Three independent leak classes —
sha1,password,email— each optional so callers pay only for the checks they configure. - Whitelists the legitimate 5-hex prefix in the range URL so the k-anonymity protocol does not trip the check.
- Treats both the literal email and its URL-encoded form as body leaks,
but allows the documented
/api/v3/breachedaccount/{encoded}and/api/v3/pasteaccount/{encoded}URL shapes. - Tolerates requests whose body cannot be cloned (some
Requestsubclasses) — failure to read the body is silent rather than fatal. - No allocations beyond what
Request.clone().text()requires.
Usage: Basic Example
import { assertNoLeak } from "@suaveplan/hibp";
await assertNoLeak(req, { password: "hunter2" });
Usage: Advanced Example
import { assertNoLeak, hashSha1Prefix } from "@suaveplan/hibp";
const { full } = hashSha1Prefix(password);
await assertNoLeak(req, { fullSha1: full, password, email });
API Reference
LeakCandidate—{ fullSha1?, password?, email? }.LeakClass—"sha1" | "password" | "email".assertNoLeak(request, candidates): Promise<void>— throws on hit.
Implementation Notes
The helper is intentionally async even though the URL check is
synchronous: reading the body requires Request.clone().text(), which
returns a Promise<string>. The check uses Array.prototype.includes
on the strings rather than per-byte iteration because JS strings already
expose indexOf in O(n), and the simpler API has fewer ways to go
wrong. The 5-hex prefix is stripped before the SHA-1 search to avoid
flagging the legitimate k-anonymity payload. Production deployments opt
in via HibpClient assertOutgoingRequestSafe: true; tests use it
unconditionally as a regression sentinel.