API surface area and reachable attack surface are related but distinct quantities. A common framing in API security treats every endpoint as equally dangerous simply by virtue of existing. That framing leads to defensive investment being distributed uniformly across the surface rather than concentrated at the paths where traversal to sensitive data is actually possible.
The distinction matters practically. An application with 300 API endpoints does not have 300 equivalent attack paths. Some endpoints are protected by authentication controls that prevent unauthorized traversal. Some handlers call into business logic that never touches sensitive data stores. Some endpoints are internal-only, reachable only from within the service mesh under specific conditions. Treating all 300 as equivalent targets generates the same kind of noise problem you get from a raw CVE list without reachability context.
Entry point enumeration as the foundation of reachability
Reachability analysis starts with an accurate and complete entry point catalogue. In a REST service, that means every registered route handler. In an event-driven service, it means every registered message consumer and the topic bindings that define when it fires. In a gRPC service, it means every method registered on the server. Missing entry points produce false negatives: the analysis says a finding is unreachable because the handler that leads to it was not in the catalogue.
Static analysis of a codebase with explicit routing conventions, such as a Spring Boot application using @RequestMapping annotations or an Express.js service using router.get() calls, produces a high-fidelity entry point catalogue because the routing declarations are syntactically explicit and machine-readable. The harder cases are dynamically registered routes, routes defined in configuration files loaded at runtime, and endpoints generated by code generation tooling where the source annotations are in a schema file rather than the application code itself. Each of these requires a different extraction strategy to maintain catalogue completeness.
The call graph from entry point to sink
Once entry points are enumerated, the analysis constructs a call graph from each entry point through the handler logic, middleware stack, service utility calls, and any outbound calls to downstream services. The traversal continues until it either reaches a known sensitive sink (a database query, a call to a secrets store, a write to a PII-bearing data structure) or exhausts the call graph without finding one.
The middleware stack deserves specific attention because it is where authentication and authorization checks live. A path that passes through a middleware layer enforcing JWT validation and role-based authorization is reachable in the technical sense: an attacker can send a request to that endpoint. But the probability of traversal to a sensitive sink is materially different from a path that requires no authentication at all. Some teams model this as separate reachability tiers: unauthenticated reachability and authenticated-but-low-privilege reachability, with the latter representing a different remediation urgency.
We are not arguing that authenticated endpoints should be ignored. The reachability verdict on an authenticated endpoint still matters. If a vulnerability in a library is reachable only from an endpoint that requires a valid admin session, the scope of who can exploit it is narrowed significantly compared to a public endpoint, but it is not zero. The distinction is in how urgently the remediation needs to be scheduled, not in whether it needs to happen at all.
How API surface growth changes the graph
Each new endpoint introduced to a service potentially adds new traversal paths through the application graph. The security consequence of adding an endpoint depends on where the handler code calls into the existing codebase. A new endpoint that only calls into already-instrumented, security-reviewed business logic has limited impact on the reachability profile. A new endpoint that introduces a new call chain into shared infrastructure code, or that calls a library function that was previously unreachable from any external entry point, can materially expand the attack surface even if the endpoint itself is straightforward.
This is the mechanism by which API surface growth affects attack surface: not through the new routes themselves, but through the new paths those routes create through the underlying code. A service with 50 endpoints and a shallow call graph has a different reachability profile than a service with 50 endpoints and a deep, interconnected call graph that routes through shared infrastructure code with known vulnerability findings.
In a microservice architecture, there is a second-order effect. A new endpoint in service A may open new traversal paths not just within service A but through service B and service C that service A calls. The inter-service reachability consequence of adding an endpoint to one service can be non-obvious without a graph model that spans service boundaries.
Internal service endpoints and the lateral movement model
Internal API endpoints warrant careful treatment in the reachability model. An endpoint that is accessible only from within the service mesh, under a network policy that allows calls only from specific peer services, is not directly accessible to an external attacker. But it is accessible to any service that can call it, and if any of those peer services has an externally reachable vulnerability, the internal endpoint becomes a lateral movement target.
The relevant question for an internal endpoint is not "is it publicly accessible" but rather "what is the shortest reachable path from an external entry point, potentially spanning multiple service hops, that reaches this endpoint and then continues to a sensitive data sink?" A two-hop path from a public endpoint through a compromised internal service to an admin API on a second internal service is still a reachable attack path from an attacker's perspective.
Modelling this correctly requires the inter-service call graph, not just the per-service call graph. Building that graph from runtime data rather than guessing from code is the difference between a model that reflects how the application actually behaves and a model that reflects how you think it behaves.
Keeping the entry point catalogue current
API surface changes constantly. Routes are added, deprecated, and occasionally removed. The reachability model needs to track those changes because an out-of-date entry point catalogue produces stale reachability verdicts. A finding classified as unreachable based on last month's entry point catalogue may be reachable if a new endpoint was added last sprint that calls into the same code path.
This is an argument for treating the reachability model as a living artifact of the application rather than a point-in-time audit result. Scanners run continuously in modern CI pipelines; the reachability filter that interprets scanner output should update at comparable cadence. When the entry point catalogue changes, findings that were previously classified as unreachable should be re-evaluated.
See reachability analysis on your own code
Connect your repositories and apply a reachability filter to your existing scanner findings. No configuration changes to your current toolchain required.
Request early access