Threat model

What leaves your server, and what we can learn from it.

Applies to API v1 · updated 6 September 2026 · found a gap? Report it.

Short version: you send six hex characters of a salted SHA-1 and an API key. We learn that one of your keys looked up one of 16,777,216 buckets at some time. We don’t learn the password, whether it matched, or whose it was.

What leaves the client

ItemSent to knownPass?
The passwordNever. Hashing happens on your server.
The full hashNever. You keep the 34-character suffix and compare locally.
6-character prefixYes. The first six hex characters of SHA-1("Salted for knownpass.com: " + password).
API keyYes, in the x-api-key header. Identifies your account, not your user.
IP, TLS, HTTP metadataYes, as with any HTTPS request from your server. Your end user’s IP is not involved unless you call us from the browser.
Username, email, user IDNever. The endpoint has no field for them.

What a prefix tells us

Six hex characters give 166 = 16,777,216 buckets. With 20 billion entries, each bucket holds about 1,200 candidate suffixes. Stated plainly: 20,000,000,000 ÷ 16,777,216 ≈ 1,192 entries per response, roughly 80 KB of JSON before compression. From a request we can tell:

A prefix on its own does not identify a password. Even for a known-weak password, the bucket contains over a thousand strong ones with the same first six characters.

Why the salt is public, and what it does

The salt string Salted for knownpass.com: is fixed and published. It adds no secrecy; its job is domain separation:

What we log

Per request: key ID, timestamp, response code and latency, for rate limiting, abuse prevention and debugging. Access logs rotate; we keep no long-term per-key request history and have no way to connect a prefix to a person. The privacy policy is the binding version of this list.

The Try-it demo on knownpass.com sends the same 6-character prefix, from the browser, with a public shared demo key. Nothing else.

If the API is down

Design the check to fail open: on timeout, network error, 429 or 5xx, let the flow continue, log that the check was skipped, and re-check at the next login or password change. What’s at risk during an outage is that a weak password slips through until then. Nothing else in your auth flow depends on us. There is no uptime SLA yet; the status page is updated by hand.

Abuse considerations

Reconstructing the dataset

A full crawl means roughly 17 million authenticated requests, each returning about 1,200 entries, throttled per key. The response carries no counts and no plaintexts, so the result is a list of salted hashes. The core dataset is derived from public material and is planned to be released openly anyway, so we rate-limit this rather than treat it as a secret.

Using the API as an oracle

The API answers “is this password known”, never “does this password belong to user X”. It cannot confirm a credential for a target account. It could help an attacker prune a candidate list, which public wordlists already allow offline; we don’t consider that a meaningful uplift, and per-key limits cap it.

Key leakage

Keys identify a customer account, not an end user. A leaked key lets someone spend your quota; it exposes no data about your users. Rotate it in the console. The demo key is public by design and throttled.

Network observers

An observer between you and us sees TLS to api.knownpass.com and a response size. At most that narrows the request to a bucket, which is the same thing we see.

What this does not protect against

knownPass is one control. It won’t stop phishing, credential stuffing with a password that never leaked, or the absence of MFA. It removes the passwords an attacker will try first.