Skip to main content

SiteVigil

     .      o                 .               o                       .
  ______  _____  _______  ______ __      __ _____   ______   _____  _
 / ____/ |_   _||__   __||  ____|\ \    / /|_   _| / ____/  |_   _|| |
| (___     | |     | |   | |__    \ \  / /   | |  | |  ___    | |  | |
 \___ \    | |     | |   |  __|    \ \/ /    | |  | | |_  |   | |  | |
 ____) |  _| |_    | |   | |____    \  /    _| |_ | |___| |  _| |_ | |____
|_____/  |_____|   |_|   |______|    \/    |_____| \_____/  |_____||______|
   |                                                |               |
   .                                                .              \___/

One command. A security audit of any website — scored, explained, and with the fix written out for you.

sitevigil aqles.github.io
https://aqles.github.io
Score: 75/100  Grade: C  HTTP 200

[MEDIUM  ] Missing Content-Security-Policy header
           No CSP header; the page has no second line of defence against XSS.
           Fix: Add a CSP that fits your site, starting strict, e.g. Content-Security-Policy: default-src 'self'
[LOW     ] Missing X-Content-Type-Options: nosniff
           Header absent or not set to 'nosniff'.
           Fix: Add: X-Content-Type-Options: nosniff
[MEDIUM  ] No clickjacking protection
           Neither X-Frame-Options (DENY/SAMEORIGIN) nor CSP frame-ancestors is set.
           Fix: Add: X-Frame-Options: DENY (or SAMEORIGIN), or frame-ancestors 'none' in your CSP.

SiteVigil is a small Python tool with zero dependencies — standard library only. It runs the checks that turn up again and again when real websites get audited, it works as a plain CLI for humans, and it speaks MCP so AI coding agents (Claude Code, Cursor, …) can run the same audit and fix what it finds.

Why not just use a free web checker?

Fair question — sites like SecurityHeaders or Mozilla Observatory grade a page for free, and for a one-off look they're fine. SiteVigil exists for everything around that moment:

  • It hands you the patch, not just the grade. --fix generates a ready-to-commit config for your actual platform (Vercel, Netlify, Cloudflare Pages, nginx, Apache). On GitHub Pages it tells you plainly that headers are a platform limit and gives you the portable _headers file instead of a lecture.
  • It lives where you work. Terminal, CI (--fail-under, --baseline), and inside your AI agent via MCP — a web page can't fail your deploy or re-check a fix.
  • It checks more than headers. Exposed .env/.git (verified by content, not status codes), CORS reflection, cookie flags, mixed content, missing SRI, TRACE, TLS expiry, security.txt.
  • It remembers. Save a report, come back next week, and --baseline shows exactly what regressed and what got fixed — web checkers have no memory of your last scan.

What it checks

Area Checks
Transport HTTPS in place, HTTP → HTTPS redirect, TLS protocol, certificate expiry, redirect chains (downgrade hops, chains over 3 hops)
Security headers HSTS, Content-Security-Policy (incl. unsafe-inline / unsafe-eval / wildcard sources), X-Content-Type-Options, clickjacking, Referrer-Policy, Permissions-Policy
Cookies Secure, HttpOnly (on session-like cookies), SameSite
CORS Arbitrary-origin reflection, * combined with credentials
Exposed files /.env, /.git/HEAD, /.git/config
Page content Mixed content (HTTP subresources on an HTTPS page), cross-origin scripts without Subresource Integrity
Methods & discovery HTTP TRACE enabled, missing /.well-known/security.txt
Isolation Cross-Origin-Opener-Policy, Cross-Origin-Resource-Policy, CSP hardening directives (object-src / base-uri)
Domain (via DNS) SPF and DMARC (only when the domain receives mail), CAA
Known vulnerabilities Software/version fingerprints (nginx, Apache, PHP, OpenSSL, IIS, WordPress, Drupal, Joomla) matched against NVD CVEs, verified against each CVE's vulnerable version ranges — plus jQuery and WordPress plugins (Elementor, WooCommerce, Contact Form 7, Akismet) fingerprinted from the page source
Info disclosure Server, X-Powered-By

The full catalog — 30+ checks, each with its reference — is one command away: sitevigil --checks. Checks are versioned as a ruleset (currently 2026.11); every report names the ruleset that produced it, and changes land in CHANGELOG.md, never silently. To keep a site up to date automatically, drop in the weekly GitHub Action from examples/github-action: it re-audits on a schedule and fails on score drops or regressions.

Every finding includes what was actually observed and a concrete fix — not just a warning label.

Two details that took real-world pain to learn:

  • No soft-404 false positives. Many sites (SPAs, some hosts) answer 200 with their homepage for every path. SiteVigil only reports an exposed file when the response content actually matches a real .env / git file — a bare 200 is never enough.
  • CVE matches are verified, not googled. NVD search happily returns CVEs that only mention your software. SiteVigil re-checks every candidate against the CVE's own vulnerable configurations and version ranges before reporting it, scores it with NVD's primary CVSS, and prints the backport caveat next to every match — a version string alone never proves a server is unpatched.
  • Proxy-aware TLS. If you sit behind a corporate proxy (https_proxy), the TLS check tunnels through it with CONNECT instead of dying with WRONG_VERSION_NUMBER.

Install

pip install sitevigil        # once published to PyPI
# or straight from the repo:
pip install git+https://github.com/aqles/sitevigil
# or just run it from a clone, no install needed:
python -m sitevigil example.com

Requires Python 3.10+. That's it — nothing else gets installed.

Use it

sitevigil example.com                  # human-readable report
sitevigil example.com --json           # structured output, for scripts and agents
sitevigil example.com --markdown       # a report you can paste into an issue
sitevigil example.com --html > report.html   # one self-contained HTML report
sitevigil a.com b.com c.com            # audit several sites, with a summary table
sitevigil example.com --fail-under 80  # CI mode: exit 1 if the score is below 80
sitevigil example.com --fix            # + a ready-to-commit header config for your platform
sitevigil example.com --json > monday.json          # save a baseline
sitevigil example.com --baseline monday.json        # next week: what regressed? (exit 1 on new findings)
sitevigil example.com --crawl 10                    # audit up to 10 pages (sitemap.xml, else homepage links)
sitevigil example.com --badge > badge.svg           # an SVG score badge for your README
sitevigil example.com --no-cve                      # skip the CVE lookup (faster, fully offline)
sitevigil example.com --html --output report.html   # write any format straight to a file

Scoring starts at 100 and loses points per finding (critical 25, high 15, medium 8, low 3), ending in a grade from A to F.

Let your AI agent use it

SiteVigil ships an MCP server (still stdlib-only). Local agents use stdio; hosted agents can use the HTTP transport:

sitevigil --mcp                      # stdio, for desktop/CLI agents
sitevigil --mcp-http 8900            # HTTP on localhost, for hosted agents

MCP is a shared protocol, so one server works with every MCP-compatible agent — Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, Gemini CLI — no per-agent builds. Only the config file's location changes; ready-to-paste snippets for each agent live in examples/mcp. Interoperability is not just claimed: the server is tested against the official MCP Python SDK client (initialize → tool list → a real audit_site call).

Your agent gets two tools: audit_site (the full scored report) and suggest_fix (the audit plus a ready-to-commit, platform-specific header config). It can check a site before telling you it's "secure" — or audit the fix it just deployed.

Honest limits

  • It audits the response of the URL you give it (plus /.env / /.git probes). It is not a vulnerability scanner and it does not fuzz, brute-force, or log in anywhere.
  • Only audit sites you own or have permission to test. The probes are read-only GETs, but scanning other people's property without permission is still a bad idea.
  • A high score means these basics are in place. It is not a guarantee that a site is secure.

Development

git clone https://github.com/aqles/sitevigil
cd sitevigil
PYTHONPATH=src python -m unittest discover -s tests -v

The test fixture is a local HTTP server that deliberately serves a soft-404 for unknown paths and a real-looking .env file — the audit has to catch one and ignore the other.

License

MIT — see LICENSE. Use it, fork it, ship it; just keep the copyright notice. If SiteVigil saves you from shipping a site with an exposed .env, a star is the going rate.

Metadata

Release files for sitevigil 0.8.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 sitevigil 0.8.0
File Size Uploaded Provenance Actions
sitevigil-0.8.0.tar.gz 35.4 kB Without provenance Details for sitevigil-0.8.0.tar.gz

Built distribution (wheel)

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

Total release size: 64.9 kB

Release files / sitevigil-0.8.0.tar.gz

Download URL sitevigil-0.8.0.tar.gz
Size 35.4 kB
Tags Source
SHA-256 checksum
How to use checksums
3ee2bda60e1ac05653547c42d1fbec2c0726599c3be37277e53882bd7fe9fb69
BLAKE2b-256 checksum
How to use checksums
52e72f9369f39cb8ef730126aec1fcdaf7ab18d061d5704eda19a722da38be3e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / sitevigil-0.8.0-py3-none-any.whl

Download URL sitevigil-0.8.0-py3-none-any.whl
Size 29.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4f85e7a7ac2fd9ab9c0d6764c5da34eaaa884a911b4b5804e2c10506699bc44b
BLAKE2b-256 checksum
How to use checksums
05e4f130f9066d5839d5da491c401ee4674a03c86b7f553c41c6a37c84f86878
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for sitevigil 0.8.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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