Description
Shadow APIs are API endpoints that exist in production but are undocumented, forgotten, or unknown to the current security and development teams. They arise from several common patterns: old API versions (/api/v1/) left running after a /v2/ migration, internal-use endpoints accidentally exposed to the internet, endpoints created by third-party integrations, debug routes enabled during troubleshooting and never removed, and microservices that expose their management APIs on publicly accessible ports.
CWE-1059 (Insufficient Technical Documentation) reflects the organizational root cause: lack of complete API inventory means security controls cannot be consistently applied. A09:2023 Improper Inventory Management is the OWASP API Security classification that specifically addresses this pattern. Shadow APIs are dangerous not because they are inherently broken, but because they are excluded from security reviews, penetration tests, WAF rule updates, and authentication policy enforcement. The old /v1/ endpoint may lack the rate limiting, input validation, and authorization checks added to /v2/.
Mobile applications frequently expose shadow APIs because the network traffic captured from an older app version reveals endpoints that have been removed from the current app but never decommissioned on the server. JavaScript bundles also leak API endpoints through hardcoded paths, configuration objects, and fetch calls visible in source maps.
How It Works
Penetration testers discover shadow APIs through multiple techniques:
# Enumerate API versions via path brute-force
ffuf -u https://api.example.com/FUZZ/users \
-w versions.txt \
-mc 200,301,401,403
# versions.txt: v1, v2, v3, api, rest, mobile, internal, admin, beta, dev
# Extract API endpoints from JavaScript bundles
curl -s https://example.com/static/js/main.chunk.js | \
grep -oP '/api/[a-zA-Z0-9/_-]+' | sort -u
# Enumerate via Wayback Machine — finds historically exposed endpoints
gau --subs example.com | grep "api" | grep -v "static\|image\|font"
Captured mobile app traffic reveals a shadow internal endpoint:
GET /api/internal/admin/users/export HTTP/1.1
Host: api.example.com
X-Internal-Client: mobile-app-v1.2.3
This endpoint was designed for internal use but is accessible over the internet because the mobile app calls it directly. It lacks the authentication middleware applied to the public API:
HTTP/1.1 200 OK
Content-Type: application/json
[{"id":1,"email":"admin@company.com","password_hash":"$2b$12$..."},
{"id":2,"email":"user@company.com","role":"admin", ...}]
Attackers also probe common shadow API patterns:
# Common shadow API paths
curl https://api.example.com/api/swagger.json
curl https://api.example.com/api/openapi.json
curl https://api.example.com/.well-known/api-catalog
curl https://api.example.com/api/v1/debug
curl https://api.example.com/actuator/env # Spring Boot actuator
curl https://api.example.com/__debug__ # Flask debug
Impact
- Authentication bypass — Legacy endpoints may lack the JWT middleware or session checks applied to current API versions.
- Credential exposure — Debug and management endpoints expose environment variables, configuration, and internal credentials.
- Unpatched vulnerabilities — Old API versions receive security patches in the current version but remain vulnerable in deprecated-but-running versions.
- Data exfiltration — Internal export endpoints accessible from the internet allow bulk data download without authorization.
- Regulatory exposure — Data handling through undocumented endpoints may not be captured in data flow assessments, creating GDPR and HIPAA compliance gaps.
Detection
- Run
ffufordirsearchwith API-specific wordlists (SecListsDiscovery/Web-Content/api/) against all known API hosts to enumerate versioned and hidden paths. - Analyze all JavaScript bundles served by the application using
LinkFinderor manual grepping for API path patterns. - Intercept mobile application traffic using Burp Suite or mitmproxy and catalog all unique API endpoints called by the app across all user flows.
- Query the Wayback Machine and CommonCrawl for historical URLs associated with the target domain—old endpoints crawled years ago may still be accessible.
- Test known framework management endpoints: Spring Boot
/actuator/*, Django/admin/, Laravel Telescope, Node.js/__debug__. - Review cloud load balancer and API gateway configurations for listener rules that route to internal services not listed in the API documentation.
Remediation
Maintain a complete API inventory. Document every endpoint, version, and internal service in a centralized API registry. Include endpoints served by third-party integrations and generated by frameworks.
Decommission old API versions. Establish a formal deprecation policy with defined sunset dates. Remove route registrations and deploy decommissioning on the scheduled date—do not simply stop documenting.
Restrict internal endpoints at the network layer. Management, debug, and internal-only endpoints must be restricted to private network ranges using security group rules, not relying on obscurity.
Disable debug endpoints in production. Apply environment-specific configuration to disable all framework debug routes (/actuator, /__debug__, /telescope) in production deployments.
