DEV Community

Daniel Kim
Daniel Kim

Posted on

Holehe Checks 120 Login Pages in Seconds. Most of Them Never Fixed a 15-Year-Old Bug.

holehe demo

A tool that only checks whether an email address has an account somewhere shouldn't be interesting. There's no model behind it, no vector database, no agent loop. It's a Python script that sends HTTP requests to password-reset endpoints and reads the response. And yet holehe is sitting on GitHub's weekly trending page this week with 13,600+ stars, 1,800+ forks, and a growing pile of open issues from people asking it to add "just one more site."

The reason it's worth a deep dive isn't the tool itself. It's what the tool is actually measuring. Every one of holehe's 120+ site modules is, functionally, a documented account-enumeration bug — a place where a web app's "forgot password" or "sign up" flow tells you, with total confidence, whether a given email address already has an account. Holehe didn't invent this weakness. It just automated checking for it, packaged it as a single CLI command, and quietly turned it into one of the most-used OSINT reconnaissance tools on GitHub.

What it actually does

Holehe takes one input — an email address — and checks it against 120-plus online services: Twitter/X, Instagram, Discord, GitHub, Spotify, and a long tail of smaller platforms. For each service, it reports whether an account exists, and where the site's own response leaks it, whether the account has 2FA enabled or a partially-masked recovery phone/email attached.

Per its own documentation, the tool "retrieves information using the forgotten password function" and "does not alert the target email" — meaning it never actually triggers a password-reset email to land in anyone's inbox. It just asks the endpoint the question a real password reset would ask, and reads the answer off the wire.

You can run it three ways: pip3 install holehe from PyPI, clone-and-install from source, or pull the Docker image. The CLI usage is a one-liner (holehe test@example.com), and the library exposes the same checks as async Python functions built on httpx and Trio, so you can wire it into a larger pipeline and get JSON back instead of a terminal table. It's licensed GPL-3.0 and maintained mostly by its original author, megadose, with community PRs adding and fixing individual site modules.

How it works: your password-reset page as an oracle

This is the part that matters more than the star count. Almost every "forgot your password?" form on the internet has to answer one binary question before it can do anything else: does an account with this email exist? How a site answers that question — and how loudly — is the entire attack surface holehe is built on.

A well-designed reset flow gives the same response either way: "If an account with this email exists, we've sent a reset link." A response that differs — a different HTTP status code, a different error message ("no account found" vs. "check your email"), a redirect to a different page, a different response time, or even a subtly different JSON shape — turns the endpoint into what security researchers call an observable discrepancy. That's cataloged as CWE-203, and testing for it is a standard line item in authenticated penetration tests and in OWASP's web security testing methodology under account enumeration and weak password-reset testing.

Holehe's 120+ modules are, one by one, hand-written exploits of exactly this discrepancy, tuned per site. Each module knows what a "yes, this email has an account" response looks like on that specific platform, and what a "no" looks like, because someone reverse-engineered it once and committed the difference as a Python function. Multiply that by 120 sites and you get, in aggregate, a working map of which major platforms leak account existence through their password-reset or signup flow and which ones have closed the hole.

Run against a single email, holehe fires these checks concurrently via async I/O, so a sweep across all 120+ modules typically finishes in seconds rather than the minutes it would take sequentially. That speed is also why rate-limiting matters so much for the tool's usability — more on that below.

Zoom into what a single module actually looks for, and the pattern repeats across all 120+ with only the specifics changing:

  • Status code discrepancy. A 200 for a known email versus a 404 or 400 for an unknown one, even if the page content looks identical to a human eyeballing it in a browser.
  • Body content discrepancy. Different copy in the JSON payload or HTML — "we've sent you a link" versus "no account found with that email" — the single most common leak, because it's the easiest for a frontend team to write without thinking about it.
  • Redirect target discrepancy. Some flows redirect to a "check your email" page only when the account is real, and silently re-render the form (or show an inline error) when it isn't.
  • Response-shape and metadata discrepancy. A handful of holehe's modules go further than exists/doesn't-exist — they parse a partially masked recovery phone number or secondary email out of the response body, or detect whether 2FA is enabled, because some platforms include that detail in the reset flow itself to help the legitimate user pick the right recovery method.

None of these require credentials, a session, or bypassing any authentication. They're all observable from a single unauthenticated HTTP request to a public endpoint — which is exactly why the technique scales to 120+ sites checked in seconds, and why it's so cheap for holehe's maintainers to add a new module: find the discrepancy once, write a ten-line async function, done.

What changed versus what came before

Cross-referencing an email address against social platforms isn't new. What's new is that it used to cost something. Commercial people-search and OSINT aggregators like Pipl or Spokeo charge for this, sit behind a web UI, and don't tell you their methodology. Manual OSINT — the kind taught in investigator training — meant visiting each platform's reset page by hand, one at a time, and eyeballing the response.

Holehe collapses that into a free, open-source, scriptable primitive that anyone can inspect, extend, and run offline (well, mostly — see limitations). It sits in a broader 2026 wave of accessible OSINT tooling alongside projects like Sherlock (username correlation across platforms), theHarvester (domain/subdomain/email reconnaissance), and GHunt (deep-dive OSINT specifically on Google accounts). None of these tools broke new cryptographic ground — they made existing techniques cheap, fast, and reproducible, which is exactly the pattern that made holehe climb GitHub's trending page again this week even though the project itself has been around for a few years.

Why developers should actually care

If you maintain any kind of signup, login, or password-reset flow, holehe is effectively a free, continuously community-updated audit of whether your endpoint is on the "leaks account existence" list. That's the part that should get an AppSec team's attention, not the OSINT angle.

Security and compliance. Account enumeration is routinely flagged in penetration test reports and increasingly shows up in bug bounty submissions, because tools like holehe make it trivial to demonstrate. Under data-protection regimes like GDPR, confirming "this specific person has an account here" from an email address alone is itself a small information disclosure — it links a real person's identity to their presence on your platform, which is exactly the kind of inference GDPR's data-minimization principle is meant to limit.

The fix is cheap, which is the annoying part. Closing this hole doesn't require new infrastructure. It requires: identical response bodies and status codes regardless of account existence, constant-time responses (or artificial delay padding) so timing doesn't leak the answer, generic copy ("if an account exists, we've emailed a link") instead of "no account found," and rate limiting on the reset/signup endpoint itself, independent of your general API rate limits. Most of this is a one-sprint fix. The fact that it's still this common across the 120+ services holehe checks suggests it's not a hard problem, it's a forgotten one — reset flows get built once, early, and rarely get a second security pass once the "happy path" works.

It's also a maintainability signal in reverse. Holehe's module list is a rolling record of which platforms fixed their enumeration leak (their module breaks or gets removed) and which haven't (their module keeps working, PR after PR, release after release). If your product's module is still green months after a pentest flagged the same issue, that's a visible, public data point — not just an internal Jira ticket nobody prioritized.

The cost/latency/DX tradeoffs are smaller than they look. The financial cost sits almost entirely on the "didn't fix it" side: enumeration is cheap to exploit at scale (credential-stuffing operations use exactly this kind of check to prune target lists down to emails that are worth attacking), so the downstream cost is fraud and account-takeover risk, not a line item anyone budgets for the leak itself. Fixing it does add a small amount of latency by design — padding a "no account" response to match the timing of a real password-reset email dispatch is a deliberate few hundred milliseconds, not a bug. The main DX cost is on copywriting and support: a generic "if this email exists, we sent a link" message means legitimate users who mistype their email, or who have three accounts and forgot which one, get less help from the UI itself and lean on support more. That's a real tradeoff, not a free fix, and it's worth deciding on purpose rather than by accident.

Lock-in cuts the other way here. Teams that outsource authentication to a managed identity provider — Auth0, Clerk, Firebase Authentication — largely inherit generic, enumeration-resistant reset responses as a platform default, because the vendor has already had this exact conversation with their own security team. That's a real argument for the lock-in tradeoff of managed auth: you give up some control over the login flow, and in exchange you stop having to remember to re-solve a 15-year-old bug every time someone rebuilds the reset page. Teams with hand-rolled auth — still extremely common, especially in older codebases or anything that predates the current wave of auth-as-a-service — are the ones actually exposed, and they're also the ones least likely to have a recent pentest that would have caught it.

Practical use cases

  • Self-audit. Point holehe at your own team's throwaway test accounts across the services you integrate with, or better, run the same discrepancy-testing logic against your own reset endpoint as part of CI/security regression testing.
  • Authorized penetration testing and bug bounty work. Enumeration checks are a standard step in scoped, permissioned engagements; holehe automates a step that used to be manual.
  • Breach and exposure response. Incident responders checking how far an email address's footprint extends across platforms, as part of assessing blast radius after a credential leak.
  • Digital-footprint audits with consent — journalists, researchers, or individuals auditing their own online presence before a job change, a public role, or a privacy cleanup.

What holehe is not built for, despite how easy it is to point at any email address: running it against someone without their knowledge or a legal basis to do so. The tool's own README limits itself to a single line — "built for educational purposes only" — which is a common OSS disclaimer but not a technical or legal safeguard. There's no consent flow, no scope-limiting, no audit log. The gap between what the tool makes trivially possible and what its disclaimer asks you to voluntarily not do is the real ethical surface area here, and it's worth being honest about that rather than waving it away with the standard GitHub README boilerplate.

Limitations the trending-page hype skips over

The rate-limit arms race is real and it's losing ground. The platforms with the largest user bases and the most to lose from enumeration — think Google, Meta-owned properties — have invested the most in blocking exactly this kind of automated probing, through CAPTCHAs, IP-based rate limits, and increasingly aggressive bot detection. Holehe's own maintainers note that sustained or large-scale use requires IP rotation to keep working, which immediately pushes serious usage toward proxy infrastructure — a step up in cost and complexity that the "just pip install and run" pitch glosses over.

Module freshness is a real bus-factor problem. The repository shows on the order of 434 commits against 13,600+ stars and a large fork count, which is a strikingly small commit history for a project this popular — a sign that active maintenance load sits on a small number of people. When a platform changes its error page copy or its response codes (which happens more often than API versioning would suggest), the corresponding module silently starts returning wrong answers until someone notices and files a fix. There's no automated regression suite continuously verifying all 120+ modules against live endpoints, so accuracy at any given moment is only as good as the last person who happened to check that specific site.

Results quality is uneven across the module list. Some modules key off multiple response signals and are quite reliable; others rely on a single brittle string match against an error message that a platform could change without any warning. The tool reports a binary exists/doesn't-exist, but doesn't expose a confidence score per module, so a user with no visibility into the underlying HTTP responses has no way to tell a rock-solid check from a shaky one.

It doesn't verify — it infers. A "yes" from holehe means "this platform's reset flow behaves as if this email has an account," not confirmed ground truth. False positives happen when platforms change behavior; false negatives happen when platforms close the enumeration hole holehe used to exploit (a genuine security win that just looks, from holehe's side, like a missing result).

The legal ground is greyer than "no CAPTCHA bypass, no login" implies. Holehe never authenticates and never brute-forces a password, so it sidesteps the most obvious unauthorized-access tripwires. But automated, high-volume probing of third-party endpoints you don't own — even unauthenticated ones — sits close enough to territory covered by computer-misuse statutes in multiple jurisdictions (the U.S. Computer Fraud and Abuse Act among them) that security researchers generally treat "no login required" as necessary, not sufficient, for a checked-off legal green light. None of that is legal advice, and the honest answer is that the law here is unsettled and platform-dependent — which is itself a reason to keep usage inside clearly authorized scope rather than treating the tool's own "educational purposes" disclaimer as a substitute for one.

How it stacks up against the rest of the OSINT toolbox

Tool Input What it actually checks Notification risk to target Maintenance model
holehe Email address Account existence across 120+ services via reset/signup endpoint discrepancies Low — designed not to trigger reset emails Small core team, community module PRs
Sherlock Username Username registration across 400+ sites (URL/profile existence, not auth flow) Low — checks public profile URLs Large community, frequent site-list churn
theHarvester Domain/company name Emails, subdomains, employee names, IPs from search engines and public sources None — passive/OSINT-source based Actively maintained, broader recon scope
GHunt Google email/account Deep Google-ecosystem OSINT (Calendar, Maps reviews, YouTube, Photos exposure) Low, but Google-account-specific and higher legal sensitivity Smaller team, narrower but deeper scope
Commercial aggregators (Pipl, Spokeo) Name/email/phone Cross-referenced public records, social profiles, historical data Varies, opaque methodology Paid, closed-source, black-box

Holehe's niche in that table is narrow and specific: it's the only one purpose-built to abuse account-existence discrepancies specifically, rather than scraping public profile pages (Sherlock) or public search-engine indexes (theHarvester). That narrowness is also its strength — it does one mechanism well instead of trying to be a general-purpose OSINT suite.

An independent read

Holehe's real value isn't as an OSINT weapon, even though that's the framing most coverage of tools like this defaults to. Its real value is as a decentralized, continuously updated vulnerability list for one of the oldest and most boring classes of auth bug there is. Every green checkmark in its module list is a live demonstration that a specific, well-known company hasn't closed a gap that's been in security testing checklists for over a decade. That's a more interesting story than "OSINT tool goes viral," and it's one the project's own README doesn't tell, because it's framed entirely around what the tool finds on other people, not what it says about the platforms being checked.

The ethical framing is thinner than the popularity deserves. "Educational purposes only" carries no technical weight, and a tool this fast and this free is going to get used for things well outside a classroom. That doesn't make the project illegitimate — Sherlock and theHarvester carry the same disclaimer and the same dual-use reality, and dual-use security tooling has always required the user, not the software, to supply the authorization. But it does mean the "13K stars, community-loved" framing you'll see elsewhere undersells how easily this particular tool maps onto stalking and doxxing use cases that have nothing to do with security research. Both things are true at once, and a fair deep dive should say so plainly instead of picking one.

Who should actually use this

AppSec and backend teams: worth 20 minutes of your time — run it against your own product's email, confirm whether your reset flow is on the list, and fix it if it is. This is a same-sprint fix, not a roadmap item.

Pentesters and bug bounty hunters with signed scope: a solid, fast addition to the recon phase; treat its results as leads to confirm manually, not as findings to report directly, given the module-freshness caveats above.

OSINT researchers and investigative journalists: useful, but pair it with your organization's legal review before running it against anyone besides yourself or a consenting subject — the tool gives you no guardrails, so you have to bring your own.

General app developers not touching auth: skip it as a tool, but take the underlying lesson — audit your own password-reset endpoint for response-based discrepancies even if nobody's asked you to, because the fix is cheap and the tool proving the bug exists is now one pip install away for anyone curious enough to look.

What's your team's actual policy on password-reset response symmetry — is it something you test for explicitly in CI/pentest scope, or did it only ever get checked the one time a pentester happened to try it?

Sources:

Top comments (0)