Attack Surface
The mapping phase builds entrypoints, identities, trust boundaries, assets, state machines, and a role by object by action matrix from evidence rather than assumption.
Why mapping comes first
Applicability cannot be resolved without a map, and coverage cannot be audited without applicability. Mapping is therefore a prerequisite phase rather than a documentation exercise.
The map is built from evidence, not from assumptions about how the framework normally behaves. A route that exists in the router but is unreachable in the deployed build is a different fact from a route that is reachable and unguarded, and only reading the system distinguishes them.
The inventory
- Entrypoints
- Routes, RPCs, webhooks, workers, cron jobs, queues, browser extensions, and CLIs. Anything that accepts input from outside the process.
- Identities
- Users, admins, sellers, workers, services, agents, API keys, and provider accounts. Effective identity, not nominal role.
- Trust boundaries
- Browser to server, tenant to tenant, seller to seller, app to provider, app to database, agent to tool, CI to runtime.
- Sensitive assets
- Secrets, money, payouts, codes, inventory, PII, chat, tokens, and admin actions.
- State machines
- Order, refund, fulfillment, assignment, authentication and session, listing, payout.
- Persistence
- Tables, caches, object storage, queues, and logs.
- External integrations
- Providers, their callbacks, and the side effects each can trigger.
- Privileged transitions
- Every place where an action changes what a subject is subsequently allowed to do.
- Client and server import boundaries
- What actually ships to the browser bundle.
- Deployment and migration paths
- How the running system differs from the checked-in source.
The graph contract
schemas/attack-surface-v1.schema.json requires a schema version, a graph ID, a scope ID, nodes, edges, boundaries, role_object_actions, and unknowns. A title and an assumptions list are optional.
Two of those required fields are unusual and deliberate. role_object_actions forces the authorization matrix to exist as data rather than as prose. unknowns forces the map to state what it could not resolve.
Unknowns are part of the map
- An unresolved entrypoint is recorded, not omitted.
- An assumption that could not be checked belongs in the assumptions list, where a reviewer can challenge it.
- Percentage of attack surface classified versus unknown or blocked is one of the recommended adoption metrics.
Tooling
The repository ships a helper that builds the attack-surface record and renders a Mermaid graph from it, so the map can be reviewed as a diagram rather than only as JSON.
python scripts/attack_surface.py --helpThe recorded case study shows what a small map looks like in practice: one external data source, three public routes, and zero authenticated actions — which is why only 41 of the 546 hypotheses were applicable to it.