Skip to main content

PhishSage

CLI toolkit for email phishing analysis. Parses raw .eml files, runs heuristic checks against headers, links, and attachments, enriches indicators with VirusTotal, WHOIS, DNS, redirects, and SSL certificate data, optionally caches external lookups, and outputs structured JSON or Rich terminal output.

PyPI Python License: MIT Status: Active


What it does

PhishSage covers three analysis surfaces, each a CLI subcommand:

headers — SPF/DKIM/DMARC extraction and alignment checks, Reply-To/Return-Path anomalies, Message-ID domain validation, free-provider detection, timestamp drift between Date and Received, optional MX record lookup, Spamhaus DBL query, and WHOIS domain-age flagging.

links — URL extraction from body and headers, raw-IP URL detection, suspicious/uncommon TLD flagging, subdomain depth and entropy scoring (detects randomly generated domains), shortened-URL detection, free hosting platform detection, SSL/TLS certificate inspection, WHOIS domain age, VirusTotal URL lookup, redirect-chain tracing, path-depth analysis, hyphen-abuse detection, and embedded fake-TLD detection.

attachments — Listing with MIME type and size, safe attachment extraction, MD5/SHA1/SHA256 hashing, VirusTotal hash lookup, and YARA rule scanning with optional verbose string/offset output.

Enrichment is opt-in via --enrich and runs concurrently. Headers support mx, spamhaus, and domain_age; links support domain_age, certificate, virustotal, and redirects.


Installation

Base (headers + basic parsing)

pip install phishsage

With extras

pip install "phishsage[attachments]"        # MIME detection
pip install "phishsage[attachments,yara]"   # + YARA scanning
pip install "phishsage[virustotal]"         # VirusTotal URL/hash lookup
pip install "phishsage[ssl]"                # SSL/TLS certificate checks
pip install "phishsage[cache]"              # Disk caching for external enrichment lookups
pip install "phishsage[all]"                # Everything

From source

git clone https://github.com/0xlam/PhishSage.git
cd PhishSage
python3 -m venv venv && source venv/bin/activate   # Windows: venv\Scripts\Activate.ps1
pip install -e ".[all]"

VirusTotal API key (optional)

Required only if you use --vt-scan or --enrich virustotal.

export VIRUSTOTAL_API_KEY="your_key_here"

Caching

External enrichment lookups can be cached to reduce repeated API calls and network requests. Requires the cache extra.

# Enable caching with default cache directory (~/.cache/phishsage)
phishsage links -f email.eml --heuristics --enrich all --cache

# Use a custom cache directory
phishsage links -f email.eml --heuristics --enrich all --cache --cache-dir ./.phishsage-cache

Caching currently supports:

Service Cached data
VirusTotal URL and file hash lookup results
WHOIS Domain age and registrar data
Redirects Redirect chains and final status
SSL certificates Certificate issuer, subject, and validity dates
MX MX records per domain
Spamhaus DBL blacklist status per domain

Cache TTLs are configured in config.toml.


Usage

Header analysis

# Full heuristics + all enrichment, save JSON
phishsage headers -f email.eml --heuristics --enrich all --json -o results.jsonl

# Selective enrichment
phishsage headers -f email.eml --heuristics --enrich mx spamhaus

# Header enrichment with cached WHOIS lookups
phishsage headers -f email.eml --heuristics --enrich domain_age --cache

Link analysis

# Extract URLs
phishsage links -f email.eml --extract

# Full heuristics + enrichment
phishsage links -f email.eml --heuristics --enrich all

# Full heuristics + enrichment with cache
phishsage links -f email.eml --heuristics --enrich all --cache

# VirusTotal scan only
phishsage links -f email.eml --vt-scan --json

Attachment analysis

# List attachments
phishsage attachments -f email.eml --list

# Hash + VirusTotal
phishsage attachments -f email.eml --hash --vt-scan

# YARA scan (verbose)
phishsage attachments -f email.eml --yara ./rules/ --yara-verbose

# Extract to directory
phishsage attachments -f email.eml --extract ./output/

Batch processing

Pass multiple files in one run:

phishsage headers -f mail1.eml mail2.eml mail3.eml --heuristics --json -o batch.jsonl

Example Workflow

phishsage headers -f examples/sample-phish.eml --heuristics --enrich all --json -o reports/headers.jsonl
phishsage links -f examples/sample-phish.eml --heuristics --enrich all --cache --json -o reports/links.jsonl
phishsage attachments -f examples/sample-phish.eml --list --hash --json -o reports/attachments.jsonl

Run all three subcommands on the same email for full coverage. Use --cache when scanning multiple emails to avoid redundant external lookups.


Output

Without --json, PhishSage renders Rich terminal output with color-coded alerts. With --json, it outputs a structured object keyed by file path.

{
  "test.eml": {
    "flags": true,
    "results": {
      "auth": {
        "spf":  { "value": "softfail", "passed": false },
        "dkim": { "value": "fail",     "passed": false },
        "dmarc":{ "value": null,       "passed": null  }
      },
      "address_alignment": { "from_vs_reply": false, "from_vs_return": false },
      "message_id":         { "msgid_vs_from": false },
      "domain_consistency": { "from_vs_return": false, "from_vs_reply": false }
    },
    "alerts": [
      { "type": "SPF_FAIL",             "message": "SPF check failed (spf=softfail)" },
      { "type": "DKIM_FAIL",            "message": "DKIM check failed (dkim=fail)" },
      { "type": "DMARC_MISSING",        "message": "DMARC result missing from Authentication-Results header" },
      { "type": "FROM_REPLY_MISMATCH",  "message": "From domain (secure-login-verification.com) does not match Reply-To domain (gmail.com)" },
      { "type": "DATE_BEFORE_RECEIVED", "message": "Date header (2026-05-26T10:00:00+00:00) is before first Received (2026-05-26T10:35:00+00:00)" }
    ],
    "meta": { "mail_id": "bb27b099" }
  }
}

Configuration

config.toml (inside the package) controls all tunable thresholds and heuristic lists. The most useful knobs:

Heuristics

Key Default Purpose
hyphen_threshold 4 Max hyphens in hostname before flagging hyphen abuse
threshold_young 30 days Flag newly registered domains
threshold_expiring 10 days Flag soon-to-expire domains
entropy_threshold 4.0 Entropy cutoff for flagging randomly generated domain labels
subdomain_threshold 3 Max non-trivial subdomain labels before flagging
max_path_depth 4 URL path depth limit
date_received_drift_minutes 30 Max drift between Date and first Received hop
max_redirects 10 Redirect-chain follow limit
cert_recent_issue_days_threshold 30 Flag recently issued certificates

Cache

Key Default Purpose
ttl_vt 86400 seconds Cache TTL for VirusTotal results
ttl_whois 604800 seconds Cache TTL for WHOIS results
ttl_redirect 21600 seconds Cache TTL for redirect results
ttl_ssl 43200 seconds Cache TTL for SSL certificate results
ttl_mx 86400 seconds Cache TTL for MX record lookups
ttl_spamhaus 3600 seconds Cache TTL for Spamhaus DBL lookups

Lists (suspicious_tlds, shorteners, free_email_domains, abusable_platform_domains, trivial_subdomains) are all editable in the same file.


Scope & limitations

  • Triage tool, not a mail gateway. Not designed for inline enforcement or production email filtering.
  • Network-dependent enrichment. WHOIS, DNS, VirusTotal, and SSL checks require connectivity and may hit rate limits.
  • Attachment coverage. Attachment analysis currently covers listing, extraction, hashing, VirusTotal hash lookup, and YARA scanning. Deeper content inspection is planned.
  • False positives. Default thresholds are set strictly and may produce false positives depending on your environment — adjust config.toml as needed.
  • Cached enrichment may become stale. Use --cache-dir to isolate cache data per investigation, or clear the cache when fresh lookups are required.

Contributing

Bug reports, heuristic improvements, new TLD/shortener/platform entries, and additional enrichment modules are all welcome. Open an issue or PR on GitHub.


License

MIT — see LICENSE.

Metadata

Release files for phishsage 2.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for phishsage 2.5.0
File Size Uploaded
phishsage-2.5.0.tar.gz 47.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for phishsage 2.5.0
File Interpreter ABI Platform
phishsage-2.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 101.2 kB

Release files / phishsage-2.5.0.tar.gz

Download URL phishsage-2.5.0.tar.gz
Size 47.8 kB
Tags Source
SHA-256 checksum
How to use checksums
114f3f42279881a3f364e747a3d9226fa47d25d30d39920498235286a1f7bdc2
BLAKE2b-256 checksum
How to use checksums
703c5c2e47651fdd36bdd509a6b65e4c54c5d5bfc840ade28a1a3e72e6b642a4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release files / phishsage-2.5.0-py3-none-any.whl

Download URL phishsage-2.5.0-py3-none-any.whl
Size 53.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
56cddd4e60d4b10eb1ddb9edc1e140f8f34ddad8d8d4de0bccf22eda1bf4804e
BLAKE2b-256 checksum
How to use checksums
7f204d597a7e8ab452b00932e6e93715e04e14510ace07e785868e2baadb6934
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

2.5.0 This release

2 release files

2.4.0

2 release files

2.3.1

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.3.0

2 release files

1.2.1

2 release files

1.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page