How Holehe's Update Check Mechanism Works and How to Disable It
Holehe automatically checks for updates at startup by querying PyPI and running pip install --upgrade if a newer version exists, but this behavior can only be disabled by modifying the source code.
Holehe, the open-source email OSINT tool by megadose, includes a hard-coded automatic update mechanism that runs before any command-line arguments are parsed. This article explains exactly how this holehe update check works, where it's implemented in the codebase, and four methods to disable it when you need consistent, predictable behavior.
How the Automatic Update Check Works
The update mechanism is implemented entirely in holehe/core.py through two key components: the check_update() function and its invocation point in maincore().
Version Retrieval and Comparison
The check_update() function fetches the latest package metadata from PyPI using httpx:
# From holehe/core.py, lines 34-36
response = httpx.get("https://pypi.org/pypi/holehe/json")
data = response.json()
actual_version = data["info"]["version"]
This remote "version" field is compared against the locally-defined __version__ constant (currently "1.61" in the analyzed snapshot). The version string is hard-coded at the top of holehe/core.py and imported for external use via holehe/__init__.py.
Automatic Upgrade Execution
When versions differ, check_update() spawns a subprocess to upgrade the package:
- Unix-like systems: Uses
pip3(lines 69-75) - Windows: Falls back to
pip(lines 76-81)
After the subprocess completes, the program prints a message and exits immediately (lines 85-86). No email reconnaissance occurs until you restart with the updated version.
Invocation Timing
The check runs unconditionally at program startup. In maincore() at line 97, you'll find:
check_update() # <- This executes before argument parsing
args = parser.parse_args()
This placement means no CLI flags exist yet to disable the behavior—the argument parser hasn't been initialized.
Can You Disable Holehe's Update Check?
Currently, there is no built-in CLI option to disable the update check. The routine is hard-coded without conditional guards. To prevent automatic updates, you must modify holehe/core.py using one of these four approaches.
Method 1: Comment Out the Function Call
The simplest approach is to remove the invocation:
# Original (holehe/core.py ~line 97)
check_update()
args = parser.parse_args()
# Modified—update check disabled
# check_update()
args = parser.parse_args()
This stops all version checking with minimal code change.
Method 2: Replace with No-Op Stub
For a cleaner modification, redefine check_update() itself:
def check_update():
"""Disabled update check."""
pass
Place this stub anywhere before line 97, or replace the original function definition (lines 34-86).
Method 3: Add a --no-update CLI Flag
For a proper solution that preserves optional update functionality, extend the argument parser and add conditional logic:
# In ArgumentParser definition (~line 80)
parser.add_argument("--no-update", action="store_true",
help="Skip the automatic update check")
# Replace unconditional call with conditional (~line 97)
if not args.no_update:
check_update()
args = parser.parse_args()
This requires editing both the parser setup and the invocation point.
Method 4: Environment Variable Guard
Modify check_update() to respect an environment variable:
def check_update():
"""Check and update holehe if not the last version."""
import os
if os.getenv("HOLEHE_NO_UPDATE"):
return # Skip update when env var is set
# ... rest of original function unchanged ...
Then disable updates per-session:
export HOLEHE_NO_UPDATE=1
holehe user@example.com
Key Files and Code Locations
| File | Purpose | Relevant Lines |
|---|---|---|
holehe/core.py |
Defines __version__, check_update(), and program entry point |
Lines 34-86 (update logic), line 97 (invocation) |
holehe/__init__.py |
Package initialization, version export for external use | Version import from core.py |
All update-related functionality is contained in holehe/core.py. No other files in the repository reference the update logic, making modifications straightforward.
Practical Implications
The holehe update check behavior has several operational consequences:
- Network dependency: Startup fails if PyPI is unreachable (unless you apply a modification)
- Unexpected exits: Valid reconnaissance runs may terminate mid-execution for upgrades
- Environment inconsistency: Automated pipelines or containerized deployments may experience version drift
- No audit trail: The subprocess upgrade happens silently without logging the change
For production OSINT workflows, disabling the automatic update is often essential to ensure reproducible results.
Summary
- Holehe's
check_update()inholehe/core.pyqueries PyPI at every startup and auto-upgrades viapipwhen versions differ - The check runs unconditionally at line 97, before CLI argument parsing
- No built-in flag exists to disable updates—modification is required
- Four viable approaches: comment the call, stub the function, add
--no-updateflag, or implement environment-variable guard - All changes are localized to
holehe/core.py
Frequently Asked Questions
Does Holehe require internet access to run?
Yes, both for the update check and for its core OSINT functionality. Even if you disable the update mechanism, Holehe needs network connectivity to query email services. The update check specifically requires access to https://pypi.org/pypi/holehe/json.
Will Holehe lose data if it updates mid-scan?
Holehe exits immediately after upgrading, so any in-progress scan is interrupted. Data from completed modules is lost because the process terminates before results are finalized. Always complete operations before allowing an update, or disable automatic updates for long-running batches.
Can I pin Holehe to a specific version without modifying code?
Not through official mechanisms. Standard Python approaches like pip install holehe==1.61 only affect initial installation—the tool still checks for updates and may upgrade itself. Source code modification remains the only reliable method to freeze functionality.
Is the update check a security risk?
The mechanism itself uses HTTPS to PyPI and subprocesses the standard pip installer, which is relatively benign. However, automatic code execution without user consent violates least-privilege principles in controlled environments. The exit-on-upgrade behavior can also disrupt forensic chain-of-custody for OSINT investigations.
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 →