Attack Surface
The attack surface is the set of places an attacker can send input or trigger behaviour — and reducing it is usually cheaper, more durable and more measurable than defending every entry you leave open.
Frame the problem
Security starts with a concrete asset, attacker capability and trust crossing.
Three questions, in order
Attack surface analysis is a triage tool. List every entry point, then answer three questions about each one, and the priority order falls out without argument.
Which of these can an attacker reach? Not "which are documented" — which *answer*. Old API versions still routed, a staging host with production data, a health endpoint that dumps configuration, an object store with a guessable name, a mobile app's hard-coded base URL pointing at an internal service.
Which require authentication? An unauthenticated endpoint is available to the entire internet in parallel, forever. That is a different risk class from something behind login, and it is where scanning finds things first.
Which perform privileged actions? An endpoint that reads a public product catalogue and an endpoint that issues a refund are both "an API route". Only one of them turns a bug into money. Sorting by privilege rather than by traffic is what stops teams from hardening the busiest endpoint instead of the most dangerous one.
| Entry point | Typically reachable by | The question that matters |
|---|---|---|
| Public endpoints | Anyone on the internet | What can be done here with no account at all? |
| Login and registration | Anyone | Can it be used to enumerate users, or to try credentials in bulk? |
| Authenticated API | Any customer | Can one customer name another customer's resource id and get it? |
| Admin endpoints | Staff — in theory | Is that enforced server-side, or by not linking to it in the UI? |
| File uploads | Any customer | Where does the file land, who can fetch it, and what parses it? |
| Webhooks | Anyone who knows the URL | Is the signature verified before the payload is trusted? |
| External integrations | A partner — and anyone who compromises them | What can that integration do inside our system? |
| Database access | Services, operators, backup jobs | How many identities can read the whole table, and why? |
| Cloud APIs | Anything holding a credential | What is the widest policy attached to a workload that faces the internet? |
| AI tools | Whatever the model decides to call | Which tools have side effects, and who authorizes them? |
Surface is a function of who you are
A single map is not enough, because the surface visible to an anonymous scanner is not the surface visible to a paying customer, and neither resembles the surface visible to a compromised background worker. Model at least three vantage points, and the interesting findings are usually in the second and third.
From anonymous, the surface is login, registration, password reset, public content, webhooks, and whatever DNS and certificate transparency reveal. From authenticated low-privilege, it expands to the entire product API — and this is where object-level authorization bugs live, because now every resource id is guessable and reachable. From compromised internal component, the surface is the internal network: service-to-service endpoints with no authentication, the metadata service, admin tooling, and the database itself.
That third vantage point is why Server-Side Request Forgery (SSRF) is so valuable to an attacker and why Egress Security exists: turning "I can make the server fetch a URL" into "I am now an internal client" collapses two of the three surfaces into one.
Reduction beats hardening
Every entry point you keep must be defended forever, by every future engineer, through every refactor. Every entry point you remove is defended permanently for free. This asymmetry is why surface reduction is the highest-return security work available to most teams and why it rarely appears in a vulnerability scanner's output.
Concretely: delete the API version nobody calls; require authentication on the endpoint that "does not return anything sensitive" (it returns timing, existence and error text); move the admin panel behind a separate network path rather than a role check alone; take the debug route out of the production build rather than gating it on a flag; stop the service from being able to make arbitrary outbound requests at all.
Surface also grows silently, which is the real problem. Each deploy can add routes, each dependency can add a listener, each cloud resource defaults to some exposure. The durable fix is an inventory that is generated rather than maintained by hand — routes enumerated from the router, cloud resources from the provider API, public buckets from a scheduled check — so that "what is exposed?" has a current answer rather than a last-quarter answer.
Key points
- Ask in order: reachable, authenticated, privileged. The last one sets priority; the first one is the one teams get wrong.
- Map the surface separately for anonymous, authenticated and internal-compromise vantage points — the last two hold the interesting findings.
- Removing an entry point defends it forever; hardening one defends it until the next refactor.
- Surface grows with every deploy, so the inventory must be generated from the running system, not maintained in a document.
- SSRF is valuable precisely because it converts the outer surface into the internal one.
Attack Surface Mapper
Change the system and observe which assumption moves.
- • Browser → API: authenticate the caller, validate the data and authorize the operation.
- • Backend → Database: authenticate the caller, validate the data and authorize the operation.
- Unmarked: User → Browser, API → Backend. If the other side were hostile, would anything here need checking?
- • Identity question: which component authenticates human and machine principals?
The builder suggests questions, not certainty. Verify each control in code, policy and production configuration; record residual risks and unknowns.
Follow the attack
Safe conceptual simulation: capability → missing control → crossed boundary → asset impact.
- 1Attacker → enumeration: DNS records, certificate transparency logs, JavaScript bundles, mobile app strings, error messages, and simple path guessing.
- 2Enumeration → inventory: a list of hosts and routes, sorted by "answers without credentials" and "sounds privileged".
- 3Inventory → probing: send malformed, oversized, unexpected-type and unauthorized-id requests and read the differences in response codes, timing and error text.
- 4Probing → foothold: the endpoint that behaves differently is the one with the bug; the surface analysis just told the attacker where to spend time.
- A forgotten endpoint has no owner, no tests and no monitoring, so a bug there is both more likely and less likely to be noticed.
- Staging and preview environments with production data turn a low-priority environment into a full data-exposure path.
- Every additional exposed integration adds not only its own risk but the risk of the partner who holds its credentials.
Defend, detect, recover
One prevention is a single point of security failure. Layer it and make failure observable.
- • Generate the route and resource inventory automatically and diff it on every deploy; new public exposure should require a decision, not a merge.
- • Default new endpoints to authenticated and new storage to private; make "public" the explicit, reviewed exception.
- • Delete deprecated API versions on a schedule rather than leaving them routed indefinitely.
- • Separate admin surfaces by network path and identity, not only by a role check inside the same application.
- • Scheduled external scans from outside your own network, so you see what an attacker sees rather than what your VPN shows you.
- • Alert on cloud configuration changes that increase exposure: a bucket policy, a security group opened to `0.0.0.0/0`, a load balancer added.
- • Watch for traffic to routes that receive no legitimate traffic — an endpoint whose only callers are scanners is a candidate for deletion.
- • Remove exposure first (close the route, make the bucket private, revoke the integration), then work out what was reached.
- • Treat any data in a wrongly exposed store as exposed for the entire period it was exposed, not from the moment you noticed.
- • Add the missing inventory check as part of the fix, since the same class of exposure will recur otherwise.
- • You cannot enumerate what you do not own: partner integrations, third-party scripts and vendor subdomains extend your surface outside your control.
- • Authenticated surface remains large by necessity; reduction helps least exactly where object-level authorization matters most.
- • Removal is politically hard — someone is always using the old version — so surface tends to ratchet up.