SuperAPI AI Directory

security-surface-audit

Security & auditing

View repository

Updated 10-15 20:05

About this skill

Security Surface Audit

Overview

Detect the project's actual threat model first, then audit only the matching attack surfaces against universal bars. A localhost CLI server, a public API, and a published library face different attackers — applying one checklist to all of them produces both noise and blind spots.

Scope is static and defensive: read code, config, and CI definitions. Never develop exploits, run PoCs, or probe live systems unless the human explicitly authorizes it — and say so in the report.

When to use / when NOT

Use when:

  • Pre-release or pre-handoff audit of what a project exposes.
  • A new surface appeared: embedded server, deploy pipeline, process-spawning command, public package.
  • Someone asks "is this exposed / safe / hardened?" about existing code.

Do NOT use when:

  • Someone is adding auth, input handling, secrets, or payment code and wants implementation guidance → see security-review.
  • You need vulnerability definitions, root causes, or taxonomy → see top-100-web-vulnerabilities-reference.
  • The ask is penetration testing or exploit development → out of scope without explicit authorization.
  • The ask is only "scan my dependencies for CVEs" → use a scanner; this skill audits code/config posture, not advisory databases.

How it works

  1. Detect surfaces. Read workspace manifests, server entry points, bind addresses/ports, CLI entry points, child_process/spawn usage, publish config (exports, files, registry), CI workflow files, Dockerfiles, deploy config. Classify every surface present:

    Surface class Detection signals
    Public web app SPA/SSR framework, deployed to a public host, user sessions, DOM rendering of dynamic data
    API service Route handlers, auth middleware, DB access, public deploy target
    Local/loopback server HTTP/WS server started by a CLI or dev tool, bound to localhost, browser-facing UI (illustrative example: a Hono control server embedded in a CLI binary)
    CLI spawning processes spawn/exec/execa, git/package-manager invocation, file installs (illustrative example: a shadcn-style "add component" installer CLI)
    Library consumed by others Publishable package, exported functions receiving caller input
    Static site + deploy pipeline Docs/marketing build, CI workflows that publish artifacts
    Desktop-embedded server Electron/Tauri/desktop app with internal HTTP/WS/IPC listener (same class as loopback, plus IPC)

    A project can have several. Enumerate all of them; missing a surface is the worst failure mode of this skill.

  2. Write a one-line threat model per surface: who attacks it, through what channel. (Loopback server → any website open in the user's browser. CLI installer → a malicious registry item. Library → any hostile caller input.)

  3. Apply only the matching check blocks from the Quality bar below. Do not run public-web checks against a loopback server or vice versa — severity depends on the threat model.

  4. Trace untrusted input flows (applies to nearly every surface): where does ingested content — repo files, external JSON, network responses, model/LLM output — reach a sink (prompt, terminal, DOM, shell, file path, object merge, URL fetch)?

  5. Severity-rate every finding (scale in Output) and cite the CVE class where one exists — named prior art makes findings credible and non-hypothetical.

  6. Emit the report in the exact Output shape. State the static/defensive scope line verbatim.

  7. Scale: on large multi-surface repos, dispatch one agent per surface and converge — see convergence-loop.

Quality bar (2026 snapshot)

Distilled 2026-06 from a researched state-of-the-art bar (CVE list and framework defaults verified 2026-06-10). Refresh note: re-verify the named advisories, browser mitigation status, and middleware defaults when auditing after ~mid-2027 or when a referenced framework major-bumps.

Local/loopback servers — the class teams get wrong

Check Bar Prior art (cite in findings)
Bind address 127.0.0.1, never 0.0.0.0 "0.0.0.0-day": browsers historically let pages reach 0.0.0.0 listeners; Chromium blocking only rolled out ~v128–133 — don't rely on browser fixes
Host header Allowlist-validate on every request DNS rebinding defeats same-origin even on loopback: Ollama CVE-2024-28224 (rebinding → API access/file exfil); MCP python-sdk CVE-2025-66416 (rebinding protection off by default)
Origin / CORS Validate Origin; CORS as explicit allowlist, never * esbuild GHSA-67mh-4wv8-2f99 (dev server sent Access-Control-Allow-Origin: *; any site could read responses). Check the framework default — e.g. Hono's hono/cors defaults origin to * (illustrative; check whatever middleware the repo uses)
Auth token Per-session token required even locally on state-changing/control endpoints MCP Inspector CVE-2025-49596 (CVSS 9.4: no client↔proxy auth + rebinding → RCE; fixed with session token + origin validation). Jupyter's token model is the positive example
CSRF Applies on localhost: simple requests need no preflight, any website can fetch()/form-POST to loopback Require Origin / Sec-Fetch-Site checks (or token) on every mutation
File serving Normalize before deny-list checks; audit traversal and bypass tricks Vite fs.deny bypass family: CVE-2025-30208 (?raw??), CVE-2025-31125, CVE-2025-46565 (/.), CVE-2025-62522 (Windows \)

Loopback binding alone is insufficient. That is the single sentence to carry into any finding on this surface.

Any server (public or local)

  • Schema-validated input at every boundary: params, query, body, headers.
  • Authn on every non-public route; per-resource authz (IDOR check on IDs in paths/bodies).
  • Secrets at rest: restrictive file permissions (0600-class), OS keyring where available; never in logs, error responses, or crash output.
  • Error messages don't leak stack traces, absolute paths, or internal versions to clients.
  • postMessage: check event.origin on receive; explicit targetOrigin (never *) when sending anything sensitive.

Untrusted ingested data (any surface that reads content it didn't author)

  • Content reaching prompts → prompt injection; reaching terminals → ANSI/OSC escape abuse (title set, clipboard write, hyperlink spoofing) — strip/encode before echo; reaching DOM → XSS — encode at the sink.
  • Object merges from external data must be prototype-pollution-safe (__proto__, constructor.prototype keys).
  • User-configurable URLs (webhooks, registries, model endpoints) → SSRF; verify auth headers/API keys do not follow redirects to attacker hosts.

CLI / process spawning

  • Spawn with argument arrays, never interpolated shell strings carrying external data.
  • External names (packages, refs, paths) used as args: guard argument injection (--flag-shaped values) with -- separators or validation.
  • Files the CLI writes: no predictable temp paths, no symlink following into privileged locations, sane permissions.

Library consumed by others

  • All caller input is hostile: ReDoS in exported regexes, prototype pollution in options merging, path handling on caller-supplied paths.
  • No eval/new Function on input; no install scripts doing undisclosed network/exec.

Supply chain / deploy pipeline

  • CI: minimal permissions: per workflow/job; third-party actions pinned to SHA; no secrets reachable from PR-triggered contexts (pull_request_target); no untrusted input (PR titles, branch names) interpolated into run:.
  • Lockfile committed; provenance/trusted publishing for public packages.
  • Static deploy: no server/API tokens baked into client bundles; restrictive headers where the host allows; no directory listing; rate limits on any serverless endpoints.

Public web app

  • XSS sinks (dangerouslySetInnerHTML, innerHTML, equivalent) only with sanitized input; CSP present or its absence justified; auth tokens not in localStorage when httpOnly cookies are feasible; no open redirects from query params.

Output

Produce exactly this report shape:

# Security Surface Audit — <project>
Date: <YYYY-MM-DD>
Scope: static, defensive review of code/config/CI. No exploit development
or live probing performed (requires explicit authorization).

## Surfaces detected
| # | Surface | Evidence | Primary threat |
|---|---------|----------|----------------|
| 1 | Local loopback server | src/server.ts binds 127.0.0.1:4317 | any website open in the user's browser |

## Findings
### [SS-1] CRITICAL — Loopback server: no Host/Origin validation
- Where: src/server.ts:42
- What: <one factual sentence>
- Class: DNS rebinding (cf. CVE-2024-28224, CVE-2025-49596)
- Fix: <smallest correct change>

(repeat per finding, ordered by severity, IDs SS-1..SS-n)

## Exposure summary
| Surface | Crit | High | Med | Low | Verdict |
|---------|------|------|-----|-----|---------|
| Loopback server | 1 | 2 | 1 | 0 | FIX-FIRST |

Overall: <one line — worst surface drives the call>

Severity scale — rate against the detected threat model, not an imagined one:

  • CRITICAL — reachable compromise (RCE, token theft, cross-origin data read) on a detected surface with no mitigating control.
  • HIGH — reachable with one realistic precondition (user visits a hostile page, installs a hostile registry item).
  • MEDIUM — defense-in-depth gap or requires unusual configuration.
  • LOW — hardening/hygiene.
  • INFO — observation; no action required.

Verdict per surface: SHIP (no Crit/High) · FIX-FIRST (any Crit/High) · HARDEN-SOON (Med-only debt worth scheduling).

Common mistakes

  • Skipping loopback servers as "local = safe", or auditing them with a public-web checklist. The loopback class has its own CVE history; use its own block.
  • Accepting CORS * because "it's only a dev server" — that is exactly the esbuild advisory.
  • Severity inflation: flagging a missing CSP on a loopback control UI as critical. Severity follows the surface's threat model.
  • Hardcoding one stack's checks ("look for Hono middleware") instead of detecting the surface first; every named tool here is illustrative.
  • Missing a surface entirely (the CI pipeline, the spawned git subprocess) because the audit fixated on the obvious server.
  • Drifting into implementation tutorials — report findings and the smallest fix; point builders to security-review.
  • Running exploit PoCs or live probes without explicit authorization.
  • Substituting dependency-scanner output for the audit; advisories complement, not replace, posture review.