surface-audit

security smoke tests for known URLs

Catch preview regressions before they ship.

surface-audit sends a small, bounded set of safe probes at a staging or preview URL and turns the result into CI-friendly output: console, JSON, Markdown, HTML, and SARIF.

boundedknown target URL
regressionbaseline and diff
CI-nativeSARIF and gates
signedSBOM + Sigstore

The problem

Preview environments move faster than security review.

A deployment can change headers, cookies, redirects, TLS behavior, CORS policy, or exposed files without changing application logic. Those changes are easy to miss in ordinary tests and too noisy for a full crawler on every pull request.

surface-audit stays intentionally narrow. It does not try to replace ZAP, Nuclei, or a human security assessment. It answers one smaller question well: did this known URL get less safe?

known URLno crawler sprawl
safe probesno exploit confirmation
review outputreports fit CI and PRs

The workflow

Run, compare, gate.

01Point at previewUse the URL your deploy system already produced.
02Scope explicitlyKeep probes bounded to approved hosts.
03Compare to baselineFocus on findings that are new or worse.
04Fail on signalGate only at the severity threshold you choose.
pipx install surface-audit

surface-audit scan https://preview.example.com \
  --scope-host preview.example.com \
  --baseline reports/baseline.json \
  --fail-on HIGH \
  --output reports/preview.sarif \
  --format sarif

GitHub Actions

Use the moving major tag, or pin the exact release.

@v1 is the stable 1.x action line. It moves to the newest compatible release, so users get patch and minor fixes. @v1.0.2 is an exact release tag for workflows that need maximum reproducibility.

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

Version surfaces

There are four names because there are four distribution surfaces.

PyPI1.0.2 is the Python package version.
GitHub Releasev1.0.2 marks the exact release commit and assets.
GitHub Actionv1 moves to the latest compatible 1.x action release.
GHCR1, 1.0, 1.0.2, and latest are container image tags.

Short version: use surface-audit==1.0.2 in Python, @v1 in GitHub Actions unless you need an exact pin, and :1.0.2 for a fully pinned container.


Outputs

Inspect the artifact before wiring it into CI.


Docs

Start small, then go deeper only when needed.