Skip to main content

surface-audit

CI PyPI Downloads Release Last commit Python License: Apache 2.0 Checked with mypy Ruff

Deterministic security smoke tests for staging, preview, and pre-deploy web apps.

surface-audit sends a small, bounded set of safe probes at a known URL and turns the result into CI-friendly findings, SARIF, Markdown, HTML, and JSON reports. It is designed for teams that want to catch security regressions in headers, TLS, redirects, cookies, CORS, exposed files, and other surface-level mistakes before they promote a build.

⚠️ Authorized use only. This tool sends real HTTP requests to the target. Only run it against systems you own or have explicit written permission to test. See SECURITY.md.

Why Teams Use It

  • Safe by default — bounded checks against a known URL, not a crawler and not an exploit framework.
  • Regression-oriented — baseline suppression and report diff help answer "what got worse?" instead of just "what exists?"
  • CI-native--fail-on, SARIF, Markdown, HTML, and JSON all fit cleanly into pull requests, code scanning, and release gates.
  • LLM-safe MCP support — the optional MCP server exposes only a host allow-listed interface.
  • Extensible — checks and renderers are pluggable via entry points.
  • Supply-chain aware — PyPI Trusted Publishing, Sigstore signatures, GitHub Releases, and CycloneDX SBOMs are built into the release flow.

Use It When

  • you have a staging, preview, or pre-production URL
  • you want a deterministic security gate in CI
  • you care about security regressions between two deployments
  • you want machine-readable output for SARIF, dashboards, or PR comments

Reach for Other Tools When

  • you need full crawling or spidering
  • you need authenticated scanning workflows
  • you want exploit confirmation or a broad template corpus

That positioning is deliberate: surface-audit is strongest as a pre-deploy security smoke test, not as a full DAST platform.

Quick Start

pipx install surface-audit

surface-audit scan https://preview.example.com \
    --scope-host preview.example.com \
    --fail-on HIGH

Detailed installation: docs/INSTALL.md.

Distribution Options

  • PyPI — best when you want the CLI in pipx, a virtualenv, or your own Python-based tooling.
  • GHCR — best when your CI prefers a prebuilt container image over installing Python dependencies at runtime.
  • GitHub Action — best when a preview-environment workflow already lives in GitHub Actions and you want the shortest integration path.

Container-first teams can use the published GHCR image on tagged releases:

docker run --rm ghcr.io/fillbyte/surface-audit:latest \
    scan https://preview.example.com --fail-on HIGH

Use the GitHub Action @v1 tag for the stable major line, or pin an exact action release such as @v1.0.4 when you want fully reproducible workflow inputs. Tagged releases also publish GitHub Release artifacts, CycloneDX SBOMs, and Sigstore signatures.

More end-to-end patterns: docs/RECIPES.md. Release and tag-management details: docs/RELEASE.md.

Security Regression Diff

# Capture a baseline once
surface-audit scan https://preview.example.com \
    --output reports/baseline.json \
    --format json

# Gate only on newly introduced HIGH+ findings
surface-audit scan https://preview.example.com \
    --baseline reports/baseline.json \
    --fail-on HIGH

# Or diff two reports explicitly
surface-audit diff reports/before.json reports/after.json \
    --output reports/diff.json \
    --fail-on-new

GitHub Action

The repository ships an action at the repo root so you can run the scan in a preview-environment workflow without hand-rolling install steps:

- name: Run surface-audit
  uses: fillbyte/surface-audit@v1
  with:
    target: ${{ steps.preview.outputs.url }}
    scope-hosts: preview.example.com
    output: reports/surface-audit.sarif
    format: sarif
    fail-on: HIGH

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v4
  with:
    sarif_file: reports/surface-audit.sarif

More end-to-end patterns: docs/RECIPES.md.

Sample Output

Target: https://preview.example.com/
Summary: HIGH 1  MEDIUM 2  LOW 1

HIGH     security-headers        Missing Content-Security-Policy header
MEDIUM   auth-cookies            Cookie 'sessionid' missing SameSite
MEDIUM   security-txt            Missing /.well-known/security.txt
LOW      directory-listing       Auto-generated index page exposed

Built-in checks

Check ID OWASP Summary
security-headers A05 Missing and weakly-configured HSTS / CSP / XFO / Referrer / Permissions
ssl-tls A02 Weak ciphers or obsolete TLS versions
https-redirect A02 Plain HTTP does not redirect to HTTPS
cross-origin-isolation A05 Missing COOP / COEP / CORP isolation headers
xss-reflection A03 Query-string input reflected without output encoding
sql-injection A03 Database error messages leaked on meta-character input
csrf A01 Mutating HTML forms without a recognizable anti-CSRF token
auth-cookies A07 Cookies missing Secure / HttpOnly / SameSite
open-redirect A01 Query parameters that allow off-origin 30x redirects
misconfiguration A05 Well-known exposed paths (.env, .git, admin consoles)
directory-listing A05 Auto-generated directory index pages
cors A05 Permissive CORS reflections and wildcard-with-credentials
security-txt A09 Missing /.well-known/security.txt (RFC 9116)

Run surface-audit list-checks to see what is registered in your environment (including any third-party plugins).

Usage

# Save a JSON report and fail CI on HIGH+ findings
surface-audit scan https://example.com \
    --output reports/example.json --format json --fail-on HIGH

# Emit SARIF for GitHub Advanced Security
surface-audit scan https://example.com \
    --output reports/example.sarif --format sarif

# Run only a subset of checks
surface-audit scan https://example.com \
    --enable security-headers --enable ssl-tls

Full CLI and library reference: docs/USAGE.md.

MCP integration

pip install "surface-audit[mcp]"
surface-audit mcp-serve --allow-host staging.example.com

This exposes scan, list_checks, list_formats, and render_report tools to local MCP clients while keeping scans gated behind an explicit host allow-list.

Project Site

The project site highlights the smoke-test workflow, GitHub Action, sample artifacts, and core adoption patterns:

Download trends remain available via PyPI Stats.

Library example

import asyncio
from surface_audit import Scanner, ScannerConfig


async def main() -> None:
    report = await Scanner(
        "https://example.com",
        config=ScannerConfig(max_concurrency=4, timeout=5.0),
    ).run()
    for finding in report.findings:
        print(finding.severity.value, finding.check_id, finding.title)


asyncio.run(main())

Extend it

Any package shipping an entry point under surface_audit.checks adds a check. A starter template for third-party checks lives under examples/plugin-template:

# your-plugin/pyproject.toml
[project.entry-points."surface_audit.checks"]
cors_wildcard = "my_checks.cors:PermissiveCORSCheck"

See docs/ARCHITECTURE.md for layering, SOLID scorecard, and design patterns.

Documentation

Development

make install   # set up .venv with dev extras
make all       # ruff + mypy + bandit + pytest

CI runs on every push across Python 3.10 – 3.13 — see .github/workflows/ci.yml.

License

Apache License 2.0 — Copyright © 2026 Uğur Kontel. See also NOTICE for attribution requirements that apply to redistributions.


surface-audit is an open-source project from Fillbyte.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

surface_audit-1.0.4.tar.gz (100.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

surface_audit-1.0.4-py3-none-any.whl (61.3 kB view details)

Uploaded Python 3

File details

Details for the file surface_audit-1.0.4.tar.gz.

File metadata

  • Download URL: surface_audit-1.0.4.tar.gz
  • Upload date:
  • Size: 100.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for surface_audit-1.0.4.tar.gz
Algorithm Hash digest
SHA256 7bdbfb43cdf470ba20b174330423f7f17ca5d34450d4cb177a79dc43cf674e0b
MD5 3913923f379a2986315716308d2be968
BLAKE2b-256 b7a7c345d1dc097ab1686faec07bd6d880ed67cd3fa35cd6ea2d6333eb44a058

See more details on using hashes here.

Provenance

The following attestation bundles were made for surface_audit-1.0.4.tar.gz:

Publisher: release.yml on fillbyte/surface-audit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file surface_audit-1.0.4-py3-none-any.whl.

File metadata

  • Download URL: surface_audit-1.0.4-py3-none-any.whl
  • Upload date:
  • Size: 61.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for surface_audit-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 5c986d1334673440ad6d9c9604b1f646f0c761ec2d2fcbb47c345df7659a0b7b
MD5 75e9eb16f6bbde3f689f2ede15db8d9c
BLAKE2b-256 65f6510263a6712265a363b74b4a56917651515eb358819d55c4be0712d002c3

See more details on using hashes here.

Provenance

The following attestation bundles were made for surface_audit-1.0.4-py3-none-any.whl:

Publisher: release.yml on fillbyte/surface-audit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.0.7

2 files

1.0.6

2 files

1.0.5

2 files

This release

1.0.4 This release

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 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