How Holehe's Password Recovery Detection Differs from Registration Checks
Holehe distinguishes between password recovery detection and registration checks by using a method attribute in each module that specifies whether to probe a service's "forgot password" endpoint or its account creation validation flow.
Holehe is an open-source OSINT tool that identifies where an email address is registered across online services. According to the megadose/holehe source code, the tool employs two distinct strategies—password recovery detection and registration checks—each encoded in a module's method attribute to determine account existence without attempting actual authentication.
Two Core Detection Strategies
Password Recovery Detection
Modules using the "password recovery" method mimic the "forgot password" flow of a target service. They submit the email address to the service's password-reset endpoint and parse the response for indicators such as masked email addresses, secondary emails, phone numbers, or success flags. Because the service only returns recovery information for registered accounts, this method reveals existence without risking account creation or triggering rate limits associated with registration attempts.
Examples of this approach appear in holehe/modules/software/adobe.py and holehe/modules/social_media/odnoklassniki.py, where the modules extract masked contact details from recovery responses to confirm account ownership.
Registration and Login Checks
Alternatively, modules with method set to "register" (or occasionally "login") emulate the sign-up process. These modules submit the target email—often accompanied by dummy credentials—to the service's registration endpoint and analyze validation errors. If the response contains strings like "email already taken" or "email is registered," the module confirms the address is associated with an existing account.
This approach is implemented in holehe/modules/social_media/facebook.py and most other social media modules where password recovery endpoints return ambiguous responses.
Architectural Implementation in holehe/core.py
The orchestration logic resides in holehe/core.py, which handles module discovery and execution strategy filtering.
Module Discovery and Loading
The import_submodules function (lines 37-48) walks the holehe.modules package to dynamically load every .py file. Subsequently, get_functions extracts the callable coroutine from each submodule along with its method metadata string.
Strategy Filtering via CLI
When users invoke the -NP or --no-password-recovery flag, the filtering logic in get_functions (lines 55-62) excludes modules where method == "password recovery", except for specific whitelisted cases. This allows investigators to avoid password-recovery flows that might send unsolicited reset emails to the target.
Async Execution Context
The launch_module function invokes each coroutine with the target email, a shared httpx.AsyncClient, and an out list. Each module appends a result dictionary containing standardized fields including exists, rateLimit, emailrecovery, and method, ensuring consistent output regardless of the internal detection strategy employed.
Code Implementation Examples
Password Recovery Detection in Adobe
In holehe/modules/software/adobe.py, the module implements the password recovery strategy by querying Adobe's authentication challenges endpoint:
# https://github.com/megadose/holehe/blob/master/holehe/modules/software/adobe.py#L5-L15
async def adobe(email, client, out):
name = "adobe"
domain = "adobe.com"
method = "password recovery"
# First request obtains an authentication state token
r = await client.post(
"https://auth.services.adobe.com/signin/v1/authenticationstate",
json={"username": email, "accountType": "individual"},
)
# Second request queries the password‑recovery endpoint
response = await client.get(
"https://auth.services.adobe.com/signin/v2/challenges",
params={"purpose": "passwordRecovery"},
)
# If a secondary email is returned, the account exists
out.append({
"name": name, "domain": domain, "method": method,
"exists": True, "emailrecovery": response['secondaryEmail'],
})
Registration Check in Facebook
Conversely, holehe/modules/social_media/facebook.py uses the registration approach by attempting a fake account creation:
# https://github.com/megadose/holehe/blob/master/holehe/modules/social_media/facebook.py#L6-L12
async def facebook(email, client, out):
name = "Facebook"
domain = "facebook.com"
method = "register"
# Submit a fake registration payload
check = await client.post(
"https://www.facebook.com/api/v1/web/accounts/web_create_ajax/attempt/",
data={
"email": email,
"username": "...random...",
"first_name": "",
"opt_into_one_tap": "false",
},
headers={"x-csrftoken": token},
)
# Facebook returns an error object; if it contains "email_is_taken"
# we know the address is already registered.
if check["status"] != "fail" and "email_is_taken" in str(check["errors"]):
out.append({
"name": name, "domain": domain, "method": method,
"exists": True, "emailrecovery": None,
})
Summary
- Password recovery detection probes "forgot password" endpoints and parses recovery responses for masked data or success indicators, using
method = "password recovery". - Registration checks simulate account creation to trigger "email already taken" errors, using
method = "register"or"login". - The
holehe/core.pyfile orchestrates strategy selection throughimport_submodulesandget_functions, with CLI flags to filter recovery-based modules. - Each strategy carries different trade-offs in stealth, rate limiting, and the potential to send unsolicited emails to targets.
Frequently Asked Questions
What is the main advantage of password recovery detection over registration checks?
Password recovery detection typically avoids triggering account creation rate limits and validation flows. By querying existing account recovery mechanisms, the method reduces the risk of alerting security systems that monitor for automated registration attempts, though it may generate password reset emails visible to the target.
How does Holehe exclude password recovery methods from a scan?
The tool filters modules based on the method attribute when users specify the -NP or --no-password-recovery command-line flag. In holehe/core.py, the get_functions logic skips modules where method == "password recovery" unless explicitly whitelisted, ensuring investigators can avoid sending unsolicited reset notifications.
Can a single Holehe module implement both detection strategies?
While the architecture supports distinct method values per module, individual modules typically specialize in one approach based on the target service's API constraints. Services like Odnoklassniki and Adobe exclusively use password recovery detection, while Facebook and Instagram rely on registration validation, as defined in their respective method attributes.
Why would a module use registration checks instead of password recovery?
Some services obfuscate their password recovery responses or require additional authentication steps that prevent reliable enumeration. In these cases, probing the registration endpoint for "email already taken" errors provides a more reliable signal of account existence, implemented in modules like facebook.py where the registration flow exposes clearer validation messages.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →