How `get_functions()` Filters Modules in Holehe Based on CLI Arguments
When you pass the -NP flag, get_functions() in holehe/core.py selectively excludes four password‑recovery modules—adobe, mail_ru, odnoklassniki, and samsung—from the execution list by inspecting string representations of the module objects.
The holehe tool dynamically discovers every site‑checking module under holehe/modules using import_submodules. The get_functions() helper then transforms those imported objects into a list of callables that execute email verification checks. This article explains exactly how that filtering mechanism works based on command‑line arguments parsed in holehe/core.py.
Where get_functions() Lives and What It Does
In holehe/core.py at lines 50‑63, the get_functions() function takes two parameters:
modules: A dictionary of imported module objects fromholehe.modulesargs: The parsedargparse.Namespacecontaining CLI flags (optional)
def get_functions(modules, args=None):
"""Transform the modules objects to functions"""
websites = []
for module in modules:
# Only consider real site modules (depth > 3)
if len(module.split(".")) > 3:
modu = modules[module] # the imported module object
site = module.split(".")[-1] # e.g. "github", "adobe", …
# ── Filtering based on the "-NP / --no-password-recovery" flag ──
if args is not None and args.nopasswordrecovery == True:
# Exclude sites that expose password-recovery helpers
if ("adobe" not in str(modu.__dict__[site]) and
"mail_ru" not in str(modu.__dict__[site]) and
"odnoklassniki" not in str(modu.__dict__[site]) and
"samsung" not in str(modu.__dict__[site])):
websites.append(modu.__dict__[site])
else:
# No filtering – keep every discovered site function
websites.append(modu.__dict__[site])
return websites
How Module Depth Filtering Works First
Before any CLI‑based filtering occurs, get_functions() applies a structural filter. It splits the module name by dots and checks if the depth exceeds 3 levels. Modules like holehe.modules.social.github pass this check (4 components), while shallower package markers get skipped. This ensures only actual site‑checking modules—not package infrastructure—are processed.
The Password‑Recovery Exclusion Logic
When args.nopasswordrecovery is True—set by the -NP or --no-password-recovery flag defined at lines 90‑92 of holehe/core.py—the function enters exclusion mode.
Why These Four Modules?
The code explicitly checks string representations of each module's callable attribute against four hardcoded names:
| Excluded Module | Reason for Exclusion |
|---|---|
adobe |
Implements password‑recovery flow for Adobe accounts |
mail_ru |
Triggers Mail.ru password‑reset mechanisms |
odnoklassniki |
Involves Odnoklassniki (OK.ru) recovery workflows |
samsung |
Executes Samsung account password‑recovery steps |
The filtering uses substring matching: str(modu.__dict__[site]) converts the function object to its string representation, and the code verifies none of the four target names appear. If clean, the module is appended to websites.
Execution Flow: From Discovery to Filtered Execution
Understanding how get_functions() fits into the broader architecture clarifies its role:
-
Discovery phase:
import_submodules("holehe.modules")recursively imports all submodules and returns a dictionary mapping module paths to module objects. -
Filtering phase:
get_functions(modules, args)applies depth and CLI‑argument filtering to produce the finalwebsiteslist. -
Execution phase: The filtered list feeds into the async nursery via
launch_module, where each callable runs concurrently with progress instrumentation fromholehe/instruments.py.
Running Holehe With and Without Filtering
# Normal run – password-recovery attempts are performed
holehe user@example.com
# Skip password-recovery (the -NP flag)
holehe user@example.com -NP
# Equivalent long form
holehe user@example.com --no-password-recovery
In the first command, all discovered modules—including adobe, mail_ru, odnoklassniki, and samsung—execute their full check logic. In the second, get_functions() excludes those four, reducing HTTP requests and avoiding rate‑limit triggers from recovery‑endpoint probing.
Key Design Decisions in the Implementation
The holehe codebase makes several interesting tradeoffs in get_functions():
-
String‑based inspection: Rather than using formal module metadata or decorators, the code inspects
str(modu.__dict__[site]). This is lightweight but fragile—renaming the excluded modules requires updating the substring checks. -
Hardcoded exclusions: The four module names are embedded directly in the conditional logic. There's no external configuration file for exclusion lists.
-
Opt‑out security: Password‑recovery checks run by default; users must explicitly request exclusion. This prioritizes thoroughness over speed unless overridden.
Summary
-
get_functions()inholehe/core.py(lines 50‑63) filters modules by depth first, then by CLI arguments. -
When
args.nopasswordrecoveryisTrue, the function string‑inspects each module's callable and excludesadobe,mail_ru,odnoklassniki, andsamsung. -
The
-NP/--no-password-recoveryflag enables this filtering, defined at lines 90‑92 of the same file. -
Filtered results flow to
launch_modulefor concurrent async execution with progress tracking.
Frequently Asked Questions
How does get_functions() know which modules to exclude?
get_functions() checks if the string representation of modu.__dict__[site] contains any of four hardcoded substrings: "adobe", "mail_ru", "odnoklassniki", or "samsung". This inspection only activates when the -NP flag sets args.nopasswordrecovery to True.
Why are only four modules excluded from password recovery?
These four modules implement explicit password‑recovery workflows that can trigger account‑recovery emails or rate‑limits. The holehe maintainers identified them as the most time‑consuming and side‑effect‑prone checks. Other modules either lack recovery flows or implement lighter verification methods.
Can I exclude additional modules using the same flag?
No. The exclusion list is hardcoded in holehe/core.py lines 56‑59. To exclude other modules, you would need to modify the source code or implement custom filtering outside the standard holehe workflow.
Where does the actual site checking happen after filtering?
After get_functions() returns the filtered websites list, holehe/core.py passes each callable to launch_module within an async nursery. This orchestrates concurrent HTTP requests with progress instrumentation from holehe/instruments.py.
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 →