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 from holehe.modules
  • args: The parsed argparse.Namespace containing 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:

  1. Discovery phase: import_submodules("holehe.modules") recursively imports all submodules and returns a dictionary mapping module paths to module objects.

  2. Filtering phase: get_functions(modules, args) applies depth and CLI‑argument filtering to produce the final websites list.

  3. Execution phase: The filtered list feeds into the async nursery via launch_module, where each callable runs concurrently with progress instrumentation from holehe/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() in holehe/core.py (lines 50‑63) filters modules by depth first, then by CLI arguments.

  • When args.nopasswordrecovery is True, the function string‑inspects each module's callable and excludes adobe, mail_ru, odnoklassniki, and samsung.

  • The -NP / --no-password-recovery flag enables this filtering, defined at lines 90‑92 of the same file.

  • Filtered results flow to launch_module for 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →