How to fix Shadow API Exposure
in ServiceStack
Executive Summary
Shadow APIs in ServiceStack often manifest as undocumented endpoints or internal services leaked via the default metadata pages and auto-generated routes. If you're not explicitly restricting your ServiceStack HostConfig and DTOs, you're handing an attacker a blueprint of your internal logic and data structures. Real-world exploitation involves scraping /metadata or /openapi to find internal services that lack the [Restrict] attribute or proper authentication.
The Vulnerable Pattern
// AppHost.cs - Default configuration leaks everything public override void Configure(Container container) { // No restriction on metadata or features }
// Services.cs - Internal service exposed to the public web public class InternalAdminService : Service { public object Any(GetSystemStats request) => new { CPU = “99%”, SecretKey = “0xDEADBEEF” }; }
The Secure Implementation
To kill shadow exposure, you must adopt a 'deny-by-default' posture. First, strip the 'Feature.Metadata' from the HostConfig in production environments to prevent automated schema discovery. Second, use the [Restrict] attribute on all DTOs that are not intended for public consumption; setting 'InternalOnly = true' ensures that only requests from your internal network or trusted proxies can reach the service. Finally, always apply [Authenticate] or [RequiredRole] at the class level to prevent unauthenticated access to 'hidden' endpoints.
// AppHost.cs - Hardening the HostConfig public override void Configure(Container container) { SetConfig(new HostConfig { // Disable metadata and debug features in production EnableFeatures = Feature.All.Remove(Feature.Metadata | Feature.Html | Feature.OpenApi), DebugMode = false }); }
// Services.cs - Explicitly restricting visibility and access [ExcludeMetadata] // Hide from any remaining discovery tools [Restrict(InternalOnly = true)] // Block non-internal network requests [Authenticate] // Ensure the caller is identified public class InternalAdminService : Service { public object Any(GetSystemStats request) => new { CPU = “99%”, SecretKey = “0xDEADBEEF” }; }
Your ServiceStack API
might be exposed to Shadow API Exposure
74% of ServiceStack 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.