Our domain showed up in a breach: what does a credential-exposure alert actually tell us, and what should we do?
DedSec Security Research ·
Suppose an alert arrives: forty-one addresses at your domain have appeared in "a new breach". Some rows show a password, some a string of hex, some a URL. Someone asks whether those people need to reset their passwords. The honest answer is that it depends on what kind of record each row is, when it was really taken, which account the address maps to, and what was on the device it came from. The alert usually tells you none of that directly.
The breach and brand monitoring post made the case for watching credential exposure, and named three things that decide whether it works: freshness, identity resolution and the reset loop. This post goes underneath them: where exposed credentials come from and why the source changes the response, why one record carries three dates, how an address does or does not map to a working credential, what to do for each class, how to stop breached passwords being set again, and what to ask of any alert.
The worked example uses the reserved domain example.com and is invented. NIST statements are quoted from SP 800-63B-4, retrieved from pages.nist.gov on 24 October 2026. Statements about the Have I Been Pwned (HIBP) APIs come from its v3 API documentation, retrieved the same day, plus one live request to the Pwned Passwords range endpoint. Publication dates are from the CSRC publication page. Everything else is general practice, not a description of how any product, ours included, processes these records.
Three kinds of record that all look like "a leak"
Exposed credentials reach monitoring by three routes. They often arrive in the same feed and the same table, and they mean different things.
A dump from one breached service
Someone compromises a single service and takes its user table: an email address, perhaps a username, and whatever the service stored in place of the password. That last column decides almost everything.
Plaintext, or reversible encryption whose key went with the data. The record holds the password the person typed. If they reused it, it works elsewhere today.
An unsalted fast hash, such as a bare MD5 or SHA-1. Fast hashes are cheap to compute, so an attacker can try enormous numbers of guesses on commodity hardware. With no salt, identical passwords produce identical hashes, so each guess tests every account at once, and precomputed tables apply directly. For human-chosen passwords, treat this as recoverable.
A salted, deliberately slow hash, such as bcrypt, scrypt, Argon2 or PBKDF2 with a high work factor. Every guess must be computed separately per account, and each one is expensive. This is what NIST asks of verifiers: SP 800-63B-4 section 3.1.1.2 says passwords "SHALL be salted and hashed using a suitable password hashing scheme", with a salt of at least 32 bits and a cost factor that "SHOULD be as high as practical". It raises cost; it does not make weak passwords safe. NIST's own appendix on password strength notes that attackers can compute "many billions of hashes per second" offline. A common password behind a slow hash is still found, later; a unique random one very likely is not.
Two inferences follow. A slow-hashed dump is a weaker signal about any individual credential, but not a reason to do nothing, because the people with weak passwords are the ones most likely to reuse them. And a plaintext password attributed to a service known to store slow hashes was either cracked from that database's hashes, captured somewhere else (phishing, malware, a server logging passwords at login), or wrongly attributed. Only the first belongs in this class. Often you will not know the storage scheme at all. Treat unknown as recoverable.
Combolists
A combolist is an aggregate: email-and-password pairs merged from earlier dumps, cracked hashes and other combolists, and redistributed as input for credential-stuffing tools. They are commonly reposted, often under a new name and billed as fresh. Three consequences for triage:
"New" usually means newly redistributed. If your monitoring has seen the pair before, the alert is a re-sighting, not new exposure.
The source is lost. A row is an address and a password, with no indication of which site, when, or whether it was ever valid. Some rows are fabricated.
It is still the attacker's input. Credential stuffing replays exactly these lists. An old pair that is still valid anywhere is a live risk.
Some corpora keep provenance. HIBP's breach model carries flags including IsVerified, IsFabricated (data "unlikely to have been hacked from the indicated website"), IsSpamList ("the data has not come as a result of a security compromise") and IsMalware. Whatever feed you use, ask whether it tells you which class a record is, or flattens them into one list.
Infostealer logs
An infostealer is malware on an endpoint. It collects what the browser stores, typically saved passwords with the URL each was used on, cookies and autofill data, and sends it to an operator; the logs are sold or shared in bulk. This class is different and more urgent, for four reasons.
The URL names the service. A dump says an address was registered on someone else's site. A stealer log row says the credential was typed into a specific URL. HIBP documents the shape as website, email and password, and supports searching by the domain of the email address and, separately, by the domain of the website "the info stealer victim was entering credentials into". If that website is your VPN portal or SSO login page, the record is a working credential for your service, not a guess about reuse.
Cookies can carry a live session. Many session tokens are bearer tokens: whoever presents the cookie is the user, and MFA already happened when the session was created. A stolen cookie can therefore get past MFA without the password. NIST SP 800-63B-4 section 5.1 notes that emerging proof-of-possession approaches, such as the device bound session credentials specification, "mitigate the risk of theft of session secrets", and may keep them in protected keystores against malware. Without that kind of binding, a password reset alone does not end a stolen session.
The device is compromised. Anything else that machine could reach, such as SSH keys, cloud CLI credentials or tokens in configuration files, should be presumed taken. The post on secrets in git history covers why an exposed credential has to be rotated, not merely removed.
The device may not be yours. Stealer logs can come from personal machines: a contractor's laptop, a family computer used to check work mail. You cannot reimage it, and your endpoint tooling never saw the infection.
Three dates on one record
Every exposed credential has at least three timestamps, and an alert may show only one.
When it was taken: the breach date, or when the stealer ran. Often approximate. HIBP documents its BreachDate field as "not always accurate - frequently breaches are discovered and reported long after the original incident".
When the corpus first saw it: HIBP records this separately as AddedDate, with ModifiedDate when more data is loaded into an existing breach.
When you were alerted: which depends on when the corpus added it, when your monitoring last queried, and when your domain was enrolled.
The gaps change triage. A breach taken years ago and first seen recently may expose a password changed long since, so compare the breach date with the account's last password change: if the change came later, the exposed password is probably stale for that account, though still worth blocking from reuse. A record first seen long ago and alerted today, because you enrolled a domain or the feed back-filled, is not new exposure and should not be counted as new in any metric. A stealer log taken recently and alerted quickly is the case where hours matter, because session cookies expire.
An alert that shows only "detected today" forces you to treat every row as fresh, which turns old combolists into incidents.
From an address to an account
A corpus records addresses. Your response acts on accounts, and only you hold the mapping.
Former staff. A leaver's address may still map to accounts that were never deprovisioned: a local login on a SaaS tool, a shared service account, an API key in their name. Treat the alert as a test of offboarding, not as noise.
Aliases and shared mailboxes. Several aliases can deliver to one person and be registered on different services. Shared mailboxes such as billing@ are often the login for a vendor portal used by several people, often with one shared password, and sometimes without MFA.
Plus-addressing. Many mail systems deliver [email protected] to [email protected]. Normalise before matching to catch more rows, but keep the original form, because it is the exact login on that service.
Personal addresses used for work. Monitoring keyed on your email domain never sees a contractor who signed up to your SaaS with a personal address. A search by website domain does: it finds every address, personal ones included, typed into your login pages. HIBP's documentation describes that search as the one an operator would use "to identify which of their customers is likely to be the subject of an account takeover attack".
SSO-backed versus local accounts. For an address that authenticates through your identity provider, a password leaked from a third-party site is a valid credential for your estate only if it was reused as the SSO password. It may still be valid on any application that accepts a local password alongside SSO: a break-glass admin account, a legacy app, a vendor portal with its own login. For each exposed address, the useful question is which applications accept a password without SSO, and whether each enforces MFA.
An invented worked example
An alert lists five rows at example.com:
ana@, from a dump of a hobby forum that used slow hashes, breached three years ago. Ana's SSO password changed last month; no local accounts. Confirm MFA and mark reviewed.
ben@, from a combolist, plaintext, first seen two years ago, alerted today because the domain was just enrolled. Ben has a local login on a legacy reporting app with no MFA. Rotate it now and move the app behind SSO.
it-admin@, from a combolist, plaintext. It is the shared login for a vendor support portal. Rotate, split into named accounts, enable MFA.
A contractor's personal address, from a stealer log, with your VPN portal URL and a session cookie for your ticketing system. Incident: revoke sessions, rotate, suspend access until the device is dealt with.
cara@, a leaver, from a breached SaaS vendor. Her identity provider account is disabled, but the vendor's admin console still has her local login. Remove it and audit that vendor's user list.
Five rows, five responses, one incident. A single "force reset for affected users" action handles the first adequately and the rest badly.
What to do, by class
Dump or combolist record:
Unless the account's password has changed since the breach date, reset the credential on every account it maps to, including local and shared logins, not only SSO.
Check MFA on each of those accounts while someone is already looking.
Ask the person where else they used that password. Your reset leaves every other site where they reused it exposed, and some of those, such as a personal cloud drive holding work files, hold your data.
Review authentication logs for the account since the breach date, or since first-seen if that is unknown.
Do it now. SP 800-63B-4 section 3.1.1.2 says verifiers "SHALL NOT require subscribers to change passwords periodically. However, verifiers SHALL force a change if there is evidence that the authenticator has been compromised." A breach record for a password that is still in use on the account is that evidence.
Stealer-log record, treated as an endpoint incident with credential consequences:
Revoke active sessions and refresh tokens on every service named in the log and on the identity provider. A reset does not end an existing session unless the service revokes sessions on reset.
Rotate every credential in the log, then everything else the device could reach.
Isolate and reimage a managed device rather than cleaning it, because you cannot easily know what else was installed.
For a personal or contractor device, suspend access until the person can authenticate from a clean device, and consider restricting access from unmanaged devices altogether.
Re-enrol MFA if the log could include backup codes or an authenticator seed.
SP 800-63B-4 section 4.3 says a credential service provider "SHALL suspend, invalidate, or destroy compromised authenticators from the subscriber's account promptly following compromise detection", and that organisations "SHOULD establish time limits for this process". Write the limit down before you need it.
Dark or deep web mention with no credential, such as a forum post offering access to example.com: a lead. Corroborate it against your own logs and the credential records above before acting.
Stop breached passwords being set again
Responding to alerts is the reactive half. The other half is refusing a known-breached password when someone sets or changes it.
SP 800-63B-4 section 3.1.1.2: "When processing a request to establish or change a password, verifiers SHALL compare the prospective secret against a blocklist that contains known commonly used, expected, or compromised passwords. The entire password SHALL be subject to comparison, not substrings or words that might be contained therein." The first example it gives is "Passwords obtained from previous breach corpuses", followed by dictionary words and context-specific words such as the service name or username. A listed password must be rejected with the reason given. SP 800-63B-4 was published in July 2025 and supersedes SP 800-63B as last updated in March 2020.
Two details are easy to miss. NIST frames the blocklist as a defence against online guessing and says "excessively large blocklists are of little incremental security benefit", because rate limiting already bounds online attacks. And it requires verifiers to offer guidance on choosing a strong password, which it calls particularly important after a blocklist rejection because it "discourages trivial modifications of listed weak passwords".
Checking without sending the password
Sending a password, or its unsalted hash, to an external service to check it discloses it. The Pwned Passwords range API avoids this with k-anonymity. As documented, and confirmed with one live request:
Compute the SHA-1 of the candidate password: 40 hexadecimal characters.
Send only the first 5 to https://api.pwnedpasswords.com/range/ followed by the prefix. No API key is needed.
The response lists the remaining 35 characters of every hash in the corpus with that prefix, each followed by a colon and the number of times it was seen. The documentation says every one of the 1,048,576 possible prefixes returns HTTP 200.
Compare locally. If your suffix is listed, the password is in the corpus.
The server learns which bucket you asked about, not which password. The header Add-Padding: true adds dummy entries with a count of 0, so the response size does not reveal the prefix to someone watching encrypted traffic; discard them. The documentation also warns against checking as each character is typed, since successive queries for a growing password can reveal it. Check once, when entry is complete. NTLM suffixes are available through a mode parameter, the corpus can be downloaded for offline checks, and HIBP's email-address range search uses the same design with a 6-character prefix and an API key.
The check belongs in the identity provider's or application's password-set flow, not in a periodic sweep.
When the feed goes quiet
A feed that stops returning data looks exactly like a feed that found nothing. An expired key, an exhausted quota or a changed response format all produce an empty result, which reads as "no exposure". The post on why a passing scan is not a scan that ran covers the general failure. Here, the practical test is whether you can see when each source last returned anything at all, not only when it last returned a match. The same holds for the look-alike domain sources beside it.
Where Maphra fits
Maphra's breach and brand monitoring tracks your domains across breach corpora, reports credential exposure by domain and dark and deep web mentions, alerts on new exposure, and surfaces the accounts that need a reset, by exposed address; mapping each address to the accounts it opens in your estate is the step described above that only you can do. It sits beside asset discovery and exposure analysis, and every finding carries the evidence that produced it.
That is the whole claim. This post does not claim that Maphra parses infostealer logs, distinguishes combolists from single-service dumps, identifies or cracks hash types, reports the three dates separately, searches by website domain, maps addresses to accounts in an identity provider, revokes sessions, or checks passwords at set time. Those are general practice, described so you can apply them with your own identity provider, logs and endpoint tooling, and so you can put the questions below to any feed, ours included.
Questions to ask of any credential-exposure alert or feed
What kind of record is it: a named-service dump, a combolist, a stealer log, or a mention with no credential?
How was the password stored at the source: plaintext, unsalted fast hash, salted slow hash, or unknown?
Which dates do I get: taken, first seen in the corpus, alerted? Which one does "new" mean?
Is it a re-sighting of a pair already reported under another breach name?
For stealer logs, which URL was the credential used on, and were cookies or tokens included?
Is the search by email domain, website domain, or both?
Which accounts does the address map to, including local logins, shared mailboxes, leavers and plus-addressed forms?
Which of those accept a password without SSO, and which enforce MFA?
Has the password changed since the breach date on each mapped account?
Does the response go beyond a reset to session revocation, device remediation and reuse elsewhere?
Do we reject breached passwords at set and change time, without sending the password anywhere?
When did each source last return any data, and would I be told if it stopped?
A credential-exposure alert says that an address and something resembling a secret were found together somewhere. Whether it is an old forum hash, a recycled combolist line or a live session cookie for your VPN, and whose account it opens, decides the response, and each row needs its own answer.