GuardAPI Logo
GuardAPI

Fix Shadow API Exposure in Spring WebFlux

Shadow APIs in Spring WebFlux are undocumented, unmonitored endpoints that bypass security controls. They usually manifest as functional RouterFunctions or legacy @RestControllers that aren't mapped in the SecurityWebFilterChain. If you aren't explicitly denying unknown paths, you're leaking attack surface. Secure WebFlux requires a 'Deny-by-Default' posture at the filter level.

The Vulnerable Pattern

@Configuration
public class ShadowConfig {
    @Bean
    public RouterFunction shadowRoutes() {
        return route(GET("/internal/debug/dump"), 
            req -> ServerResponse.ok().bodyValue("Sensitive Thread Dump..."));
    }
}

@EnableWebFluxSecurity public class SecurityConfig { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { return http.authorizeExchange(exchanges -> exchanges .pathMatchers(“/api/public/**“).permitAll() // Shadow API /internal/debug/dump is NOT matched here, // and without a final denyAll(), it might be exposed depending on global config. ).build(); } }

The Secure Implementation

To kill Shadow APIs, you must shift from an 'Allow-List' to a 'Strict-Deny' architecture. The vulnerable code fails because it doesn't account for routes defined outside the main security context. By adding '.anyExchange().denyAll()', you ensure that any 'shadow' route added by a developer—whether via RouterFunction or @RequestMapping—is unreachable unless a security rule is explicitly written for it. Furthermore, always prefix your API versions to make broad path-matching more effective and less prone to accidental exposure.

@EnableWebFluxSecurity
public class HardenedSecurityConfig {
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        return http
            .authorizeExchange(exchanges -> exchanges
                .pathMatchers("/api/v1/public/**").permitAll()
                .pathMatchers("/api/v1/private/**").authenticated()
                // The Kill Switch: Any route not explicitly defined above is dropped.
                .anyExchange().denyAll()
            )
            .csrf(csrf -> csrf.disable())
            .build();
    }
@Bean
public RouterFunction<ServerResponse> documentedRoutes() {
    return route(GET("/api/v1/private/stats"), 
        req -> ServerResponse.ok().bodyValue("Secure Data"));
}

}

System Alert • ID: 9499
Target: Spring WebFlux API
Potential Vulnerability

Your Spring WebFlux API might be exposed to Shadow API Exposure

74% of Spring WebFlux apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

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.