PCH-02-007-hibp-add-padding.patch.md
PCH-02-007 — Add Add-Padding: true to the HIBP k-anonymity range check
Severity: Informational
Target file: src/background/vault.ts:230 (checkBreach)
Report: peach-code-review.md, Finding PCH-02-007
Exact edit
// BEFORE (vault.ts:230)
const res = await fetch(`https://api.pwnedpasswords.com/range/${prefix}`);
// AFTER
// PCH-02-007: HIBP pads the response to a fixed bucket size when asked,
// so a network-position observer can't use response length to infer how
// many suffixes a prefix returned. Padding lines are random suffixes with
// count 0 — the suffix match below either misses them or parses 0, which
// every consumer already treats as "not breached".
const res = await fetch(`https://api.pwnedpasswords.com/range/${prefix}`, {
headers: { "Add-Padding": "true" },
});
Parser compatibility (verified)
Padded responses append fake SUFFIX:0 lines. checkBreach parses
text.split("\r\n").find((l) => l.startsWith(suffix)) then
parseInt(line.split(":")[1], 10):
- A padding line virtually never collides with the real 35-hex-char suffix;
if one ever did, its count parses to
0, and bothcheckBreach'smatch ?expression and every caller (breach > 0/count > 0checks in vault.ts/messages.ts) already treat 0 as not-breached. - No change needed to the response handling.
Tests
vault.hibp-padding.test.ts (in this folder) — 3 tests: header present on the
range request (fetch spy), breach count still parsed from a padded response,
padding-line count-0 is not reported as a breach.
Destination: src/background/vault.hibp-padding.test.ts.
Save message (integration)
fix: PCH-02-007 add Add-Padding header to HIBP k-anonymity range check