How to fix Shadow API Exposure
in ASP.NET Core
Executive Summary
Shadow APIs are the silent killers of your perimeter. In ASP.NET Core environments, developers often leak internal logic via undocumented debug routes, 'convenience' endpoints, or forgotten controllers that bypass central authentication. If an endpoint isn't documented, monitored, and locked down by default, it's a backdoor waiting to be discovered by a simple directory brute-force attack or a leaked Swagger definition.
The Vulnerable Pattern
[ApiController] [Route("api/[controller]")] public class InternalToolsController : ControllerBase { // VULNERABILITY: Shadow endpoint leaked to production. // No [Authorize] attribute and not documented in public API specs. [HttpGet("dump-config")] public IActionResult GetConfig() { return Ok(new { Database = "Production", SecretKey = "0x41414141" }); } }
// Program.cs - Swagger exposed in all environments app.UseSwagger(); app.UseSwaggerUI();
The Secure Implementation
To kill Shadow APIs, you must shift to a 'Secure by Default' stance. First, we implement a FallbackPolicy in Program.cs, which forces every single endpoint in the application to require authentication unless specifically overridden with [AllowAnonymous]. Second, we wrap Swagger/OpenAPI middleware in environment checks to prevent attackers from using your metadata to map hidden routes. Finally, we use explicit versioned routing and ApiExplorerSettings to ensure that internal-only logic doesn't inadvertently surface in public-facing documentation or discovery tools.
// 1. Enforce Global Authorization by default builder.Services.AddAuthorization(options => { options.FallbackPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); });// 2. Environment-based middleware gating if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); }
// 3. Explicitly opt-out only where necessary [Authorize(Roles = “Admin”)] [ApiExplorerSettings(IgnoreApi = true)] // Hide from mapping tools if necessary [Route(“api/v1/management/[controller]”)] public class InternalToolsController : ControllerBase { [HttpGet(“dump-config”)] public IActionResult GetConfig() => Ok(“Redacted”); }
Your ASP.NET Core API
might be exposed to Shadow API Exposure
74% of ASP.NET Core apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
Free Tier • No Credit Card • Instant Report
Verified by Ghost Labs Security Team
This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.