HeaderHound
HeaderHound is a defensive web-security posture auditor. It requests one authorized URL, follows a bounded redirect chain, and reports configuration signals in a readable terminal table or stable JSON. It is not a penetration-test or vulnerability-exploitation tool.
It is intended for systems you own or are authorized to assess. It does not crawl, exploit vulnerabilities, fuzz endpoints, or perform destructive actions.
Install
HeaderHound requires Python 3.10 or newer. Once a release is published to PyPI, install it with either pip or pipx:
python -m pip install --upgrade headerhound
# or, for an isolated command-line application:
pipx install headerhound
For an unreleased source checkout, use python -m pip install . instead.
Packaging and distribution
GitHub releases are the source of versioned distributions. The release workflow builds a wheel and source distribution, validates both, and publishes them to PyPI with PyPI Trusted Publishing. It uses GitHub Actions OIDC and does not store a PyPI API token in this repository.
After publication, install the latest release with:
python -m pip install --upgrade headerhound
pipx install headerhound
The published project page lists the exact wheel and source-distribution files for every release.
Usage
headerhound https://example.com
headerhound https://example.com --format json
headerhound https://example.com --json --min-score 80
headerhound https://staging.example.com --fail-on high
headerhound https://example.com --format json --fail-under 80
headerhound https://service.internal --allow-private --timeout 15
Example terminal output:
Target: https://example.com/
Final URL: https://example.com/
HTTP status: 200
Security score: 78/100 (grade C)
+----------+-----------------------------------+--------------------------------+
| Severity | Finding | Details |
+----------+-----------------------------------+--------------------------------+
| HIGH | Content-Security-Policy missing | The browser receives no policy |
+----------+-----------------------------------+--------------------------------+
Exit status is 0 for a completed scan and 2 for invalid input or retrieval failure. JSON errors are written to standard error as {"error": "..."}.
Use --fail-under SCORE to return exit status 1 when a completed scan is below a chosen CI threshold.
--min-score is an alias for --fail-under; --fail-on low|medium|high returns 1 when a finding meets that severity.
Checks
HeaderHound assesses the presence and selected high-signal weak configurations of:
Content-Security-Policy— including report-only mode, nodefault-src, wildcard sources,unsafe-inline, andunsafe-evalStrict-Transport-Security— HTTPS-only evaluation, invalid/disabled values, and shortmax-ageX-Content-Type-OptionsandX-Frame-OptionsReferrer-PolicyandPermissions-PolicyCross-Origin-Opener-Policy,Cross-Origin-Resource-Policy, andCross-Origin-Embedder-PolicySet-Cookieattributes without exposing cookie values:Secure,HttpOnly,SameSite, parent-domain scope, and long lifetimes- Passive CORS policy (
Access-Control-Allow-*), including wildcard origin/method/header settings - HTTP-to-HTTPS redirects, HSTS
max-age,includeSubDomains, andpreload - Technology disclosure headers (
Server,X-Powered-By, and ASP.NET version headers) - Conservative cache signals when a response sets a session-like cookie
The score begins at 100 and subtracts the deduction attached to each finding in the report. It is deterministic and explainable, but it is a prioritization aid—not a compliance result or a substitute for application-specific review.
JSON and CI/CD
JSON output has stable top-level target, final_url, status, score, grade, headers, cookies, cors, transport, findings, and metadata sections. Cookie values and Set-Cookie header values are never emitted. A CI job can scan an authorized staging endpoint with headerhound "$STAGING_URL" --json --fail-on high.
CORS and cache findings are passive configuration signals. HeaderHound does not send probing origins, credentials, exploit payloads, or destructive requests.
Safety and network behavior
- Only
httpandhttpsURLs are accepted; credentials embedded in URLs are rejected. - By default, targets resolving to loopback, private, link-local, multicast, reserved, or unspecified addresses are rejected. Use
--allow-privateonly on systems you are authorized to scan. - TLS certificates are verified by default.
--insecureexists only for authorized diagnostic use. - The default timeout is 10 seconds, redirects are limited to 5, and the client disables environment proxy settings. Each redirect target is rechecked against the public-address policy.
- One request is made per invocation.
--min-intervalis available for integrations which reuse the client.
Private-address filtering is a useful guardrail, not a complete SSRF defense against DNS rebinding or hostile networks. Run scans from a suitably restricted network when targets may be untrusted.
Architecture
CLI → URL validation / target policy → bounded HTTP client → header analyzer → table or JSON renderer
safety.py: URL validation and conservative public-target policyclient.py: timeouts, redirect bound, TLS policy, and retrieval errorsanalyzer.py: pure, testable header checks and score calculationoutput.py: dependency-free terminal and JSON reports
Limitations
HeaderHound evaluates one response (while reporting the redirect chain). It cannot determine whether headers are consistent on every route, whether a reflected CORS origin is authorized, whether a CSP is compatible with the application, whether TLS configuration is strong, or whether application behavior is secure. DNS-rebinding resistance also requires egress controls. Security headers are defense in depth.
Release process
Maintainers run tests, linting, formatting, python -m build, and python -m twine check dist/* before creating a matching GitHub release tag. The release workflow uses PyPI Trusted Publishing; it does not use a stored PyPI API token.
Development
python -m pip install -e '.[dev]'
ruff check .
ruff format --check .
pytest
See CONTRIBUTING.md, SECURITY.md, and ROADMAP.md.
License
MIT. See LICENSE.
Metadata
Release files for headerhound 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| headerhound-0.2.0.tar.gz | 17.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| headerhound-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.3 kB
Release files / headerhound-0.2.0.tar.gz
| Download URL | headerhound-0.2.0.tar.gz |
|---|---|
| Size | 17.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
15d068a0ca5ce3f63fe4aa9769a92f6534bddf3ae4b7849bbe9d6e5af070bffa
|
|
BLAKE2b-256 checksum How to use checksums |
875efa940502043b8ca0eaf99d144f41ec1b7366a3ce50d63eddad2681144908
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / headerhound-0.2.0-py3-none-any.whl
| Download URL | headerhound-0.2.0-py3-none-any.whl |
|---|---|
| Size | 19.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fde87d62522ad2cd06a67a1a267b24a7e8e89ebf5c97396ff03ce85e197adef6
|
|
BLAKE2b-256 checksum How to use checksums |
aa7bac3e64f205ca6dc9c5a8b7ef6747f938706c2dd565735ebe3bf7e871c5b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency log