Modular async web-application security surface auditor with pluggable checks, MCP support, and CI-friendly reports.
Project description
surface-audit
A modular, asynchronous web-application security surface auditor.
surface-audit sends a small, configurable set of safe probes at a target
URL, mapping findings to the
OWASP Top 10 (2021) categories where
applicable. It is designed for pre-deployment smoke testing, CI gates,
and as an embeddable Python library. The pluggable architecture
(surface_audit.checks entry points) keeps the tool catalog-agnostic —
third-party checks can target any standard (NIST, CIS, ASVS, internal
rules).
⚠️ 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.
Highlights
- Async by default — checks run concurrently over a shared
httpx.AsyncClientwith a semaphore cap and exponential-backoff retries. - Plugin architecture — every check is a class registered via Python entry points. Third-party packages add their own without forking.
- Multiple output formats — rich console, JSON, HTML, Markdown (PR-ready), and SARIF 2.1.0 for GitHub Code Scanning integration.
- Configurable — TOML config file (
surface-audit.tomlor[tool.surface-audit]) plus per-invocation CLI flags. - CI-friendly —
--fail-on HIGHgates builds on severity; SARIF uploads integrate natively with GitHub Advanced Security. - Typed, tested, safe —
mypy --strict,ruff,bandit, and apytestsuite with respx-mocked HTTP tests.
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).
Quick start
pipx install surface-audit
surface-audit scan https://example.com
Detailed per-platform setup: docs/INSTALL.md.
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.
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:
# 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
docs/INSTALL.md— per-platform installationdocs/USAGE.md— CLI, library, and CI recipesdocs/ARCHITECTURE.md— layering and extension pointsCONTRIBUTING.md— development workflowSECURITY.md— vulnerability disclosureCODE_OF_CONDUCT.md— community expectations
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file surface_audit-1.0.0.tar.gz.
File metadata
- Download URL: surface_audit-1.0.0.tar.gz
- Upload date:
- Size: 79.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9eafb809c0cd9a04b7b00a942b6f70c1e1b386316ec0df386167178c4662761c
|
|
| MD5 |
b15e94397d1d56ab69f8137052aa793e
|
|
| BLAKE2b-256 |
d6eaa6ad3f62d68cc0e63e7a236cb2de7d7adc5c9fc6831ac4bc40c6fe8ec00f
|
Provenance
The following attestation bundles were made for surface_audit-1.0.0.tar.gz:
Publisher:
release.yml on dev-ugurkontel/surface-audit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
surface_audit-1.0.0.tar.gz -
Subject digest:
9eafb809c0cd9a04b7b00a942b6f70c1e1b386316ec0df386167178c4662761c - Sigstore transparency entry: 1340790472
- Sigstore integration time:
-
Permalink:
dev-ugurkontel/surface-audit@745fac9638300e843699c669408077eb7ab75740 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/dev-ugurkontel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@745fac9638300e843699c669408077eb7ab75740 -
Trigger Event:
push
-
Statement type:
File details
Details for the file surface_audit-1.0.0-py3-none-any.whl.
File metadata
- Download URL: surface_audit-1.0.0-py3-none-any.whl
- Upload date:
- Size: 63.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19b4ef364489ebaa8d9ee54599e8f7dc812c9046c779febcb572ff75917e4d58
|
|
| MD5 |
aa30b9ca7c7b957128bd058c34a0afe2
|
|
| BLAKE2b-256 |
d998616bd228c646286b5458888038b268ddd8cd7c6ccad78de7b72604a1d82e
|
Provenance
The following attestation bundles were made for surface_audit-1.0.0-py3-none-any.whl:
Publisher:
release.yml on dev-ugurkontel/surface-audit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
surface_audit-1.0.0-py3-none-any.whl -
Subject digest:
19b4ef364489ebaa8d9ee54599e8f7dc812c9046c779febcb572ff75917e4d58 - Sigstore transparency entry: 1340790481
- Sigstore integration time:
-
Permalink:
dev-ugurkontel/surface-audit@745fac9638300e843699c669408077eb7ab75740 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/dev-ugurkontel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@745fac9638300e843699c669408077eb7ab75740 -
Trigger Event:
push
-
Statement type: