Performs API inventory and discovery to identify all API endpoints in an organization's environment including documented, undocumented, shadow, zombie, and deprecated APIs. The tester uses passive traffic analysis, active scanning, DNS enumeration, JavaScript analysis, and cloud resource inventory to build a comprehensive API catalog. Maps to OWASP API9:2023 Improper Inventory Management. Activates for requests involving API discovery, shadow API detection, API inventory audit, or attack surface mapping.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
performing-api-inventory-and-discovery
description
Performs API inventory and discovery to identify all API endpoints in an organization's environment including documented, undocumented, shadow, zombie, and deprecated APIs. The tester uses passive traffic analysis, active scanning, DNS enumeration, JavaScript analysis, and cloud resource inventory to build a comprehensive API catalog. Maps to OWASP API9:2023 Improper Inventory Management. Activates for requests involving API discovery, shadow API detection, API inventory audit, or attack surface mapping.
Mapping the complete API attack surface of an organization before a security assessment
Identifying shadow APIs deployed by development teams without security review
Discovering deprecated or zombie API versions that remain accessible but unmaintained
Finding undocumented API endpoints exposed through mobile applications, SPAs, or microservices
Building an API inventory for compliance requirements (PCI-DSS, SOC2, GDPR)
Do not use without written authorization. API discovery involves scanning network infrastructure and analyzing traffic.
Detection Gaps & Validation
Single-source blindness: logs alone miss APIs that never traversed the gateway; combine passive HAR/traffic, JS bundle parsing, DNS enumeration, and cloud-native inventory (API Gateway, Lambda URLs, ALB rules).
JS endpoint-extraction gaps: minified/webpack-chunked bundles, lazy-loaded chunks, and .map source maps hide endpoints - parse all chunks and source maps, not just main.js.
Non-standard locators: APIs on odd ports, vhosts, gRPC/WebSocket, and base paths outside /api or /v\d slip past keyword filters.
Zombie versions:v0/v1 left after a v2 launch rarely show in current traffic - enumerate version prefixes explicitly.
How to validate the detection fires: deploy a known undocumented endpoint and confirm it appears as shadow; cross-reference the discovered set against every documented OpenAPI source, not one file. Tune false positives by excluding health/metrics/static-asset routes and confirming "shadow" items are truly absent from all spec sources before flagging.
Prerequisites
Written authorization specifying the target domains and network ranges
f"Discovered {len(api_endpoints)} unique API endpoints:\n"
for
in
sorted
", "
sorted
"methods"
", "
"auth_types"
or
"None"
print
f" [{methods}] {url}"
print
f" Auth: {auth} | Requests: {info['count']}"
return
Step 2: Active API Endpoint Discovery
# DNS enumeration for API subdomains
amass enum -d example.com -o amass_results.txt
subfinder -d example.com -o subfinder_results.txt
# Filter for API-related subdomains
grep -iE '(api|rest|graphql|ws|gateway|backend|internal|staging|dev|v1|v2)' \
amass_results.txt subfinder_results.txt | sort -u > api_subdomains.txt
# Check which subdomains are alivecat api_subdomains.txt | httpx -status-code -content-length -title \
-tech-detect -o live_apis.txt
# Probe common API paths on each live subdomaincat api_subdomains.txt | whileread domain; dofor path in /api /api/v1 /api/v2 /graphql /swagger.json /openapi.json \
/api-docs /docs /health /status /metrics /actuator; do
curl -s -o /dev/null -w "%{http_code} %{url_effective}\n" \
"https://${domain}${path}" 2>/dev/null | grep -v "^404"donedone
import requests
import concurrent.futures
defdiscover_api_endpoints(base_domains):
"""Actively probe for API endpoints across discovered domains."""# Common API paths to test
API_PATHS = [
"/api", "/api/v1", "/api/v2", "/api/v3",
"/graphql", "/gql", "/query",
"/rest", "/json", "/rpc",
"/swagger.json", "/swagger/v1/swagger.json",
"/openapi.json", "/openapi.yaml", "/api-docs",
"/docs", "/redoc", "/explorer",
"/.well-known/openid-configuration",
"/health", "/healthz", "/ready",
"/status", "/info", "/version",
"/metrics", "/prometheus",
"/actuator", "/actuator/health", "/actuator/info",
"/admin", "/admin/api", "/internal",
"/debug", "/debug/vars", "/debug/pprof",
"/ws", "/websocket", "/socket.io",
"/grpc", "/twirp",
]
discovered = []
defcheck_endpoint(domain, path):
for scheme in ["https", "http"]:
url = f"{scheme}://{domain}{path}"try:
resp = requests.get(url, timeout=5, allow_redirects=False,
verify=False) # TLS verification disabled for discovery; enable in productionif resp.status_code notin (404, 502, 503):
return {
"url": url,
"status": resp.status_code,
"content_type": resp.headers.get("Content-Type", ""),
"server": resp.headers.get("Server", ""),
"size": len(resp.content),
}
except requests.exceptions.RequestException:
passreturnNonewith concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
futures = {}
for domain in base_domains:
for path in API_PATHS:
future = executor.submit(check_endpoint, domain, path)
futures[future] = (domain, path)
for future in concurrent.futures.as_completed(futures):
result = future.result()
if result:
discovered.append(result)
print(f" [FOUND] {result['url']} -> {result['status']} ({result['content_type']})")
return discovered
Step 3: JavaScript Source Analysis for API Endpoints
import re
import requests
defextract_apis_from_javascript(js_urls):
"""Extract API endpoints from JavaScript source files."""
api_pattern = re.compile(
r'''(?:['"`])((?:/api/|/v[0-9]+/|/graphql|/rest/)[^'"`\s<>{}]+)(?:['"`])''',
re.IGNORECASE
)
url_pattern = re.compile(
r'''(?:['"`])(https?://[a-zA-Z0-9._-]+(?:\.[a-zA-Z]{2,})+(?:/[^'"`\s<>{}]*)?)(?:['"`])'''
)
fetch_pattern = re.compile(
r'''(?:fetch|axios|ajax|XMLHttpRequest|\.get|\.post|\.put|\.delete|\.patch)\s*\(\s*(?:['"`])([^'"`]+)'''
)
all_endpoints = set()
for js_url in js_urls:
try:
resp = requests.get(js_url, timeout=10)
content = resp.text
# Extract relative API pathsformatchin api_pattern.findall(content):
all_endpoints.add(("relative", match))
# Extract absolute URLsformatchin url_pattern.findall(content):
ifany(kw inmatch.lower() for kw in ["/api", "/v1", "/v2", "graphql"]):
all_endpoints.add(("absolute", match))
# Extract from fetch/axios callsformatchin fetch_pattern.findall(content):
all_endpoints.add(("fetch", match))
except requests.exceptions.RequestException:
passprint(f"\nAPI endpoints discovered from JavaScript ({len(all_endpoints)}):")
for source, endpoint insorted(all_endpoints):
print(f" [{source}] {endpoint}")
return all_endpoints
# Find JavaScript files from the target domaindeffind_js_files(domain):
"""Discover JavaScript files from a web application."""
resp = requests.get(f"https://{domain}", timeout=10)
js_files = re.findall(r'src=["\']([^"\']+\.js[^"\']*)', resp.text)
full_urls = []
for js in js_files:
if js.startswith("http"):
full_urls.append(js)
elif js.startswith("//"):
full_urls.append(f"https:{js}")
elif js.startswith("/"):
full_urls.append(f"https://{domain}{js}")
return full_urls
Step 4: Cloud API Gateway Inventory
import boto3
definventory_aws_apis():
"""Inventory all APIs in AWS API Gateway."""
apigw = boto3.client('apigateway')
apigwv2 = boto3.client('apigatewayv2')
apis = []
# REST APIs (API Gateway v1)
rest_apis = apigw.get_rest_apis()
for api in rest_apis['items']:
resources = apigw.get_resources(restApiId=api['id'])
stages = apigw.get_stages(restApiId=api['id'])
for stage in stages['item']:
for resource in resources['items']:
for method in resource.get('resourceMethods', {}).keys():
apis.append({
"type": "REST",
"name": api['name'],
"stage": stage['stageName'],
"path": resource['path'],
"method": method,
"url": f"https://{api['id']}.execute-api.{boto3.session.Session().region_name}.amazonaws.com/{stage['stageName']}{resource['path']}",
"created": str(api.get('createdDate', '')),
})
# HTTP APIs (API Gateway v2)
http_apis = apigwv2.get_apis()
for api in http_apis['Items']:
routes = apigwv2.get_routes(ApiId=api['ApiId'])
stages = apigwv2.get_stages(ApiId=api['ApiId'])
for route in routes['Items']:
apis.append({
"type": "HTTP",
"name": api['Name'],
"route": route['RouteKey'],
"api_id": api['ApiId'],
"protocol": api['ProtocolType'],
})
print(f"\nAWS API Inventory ({len(apis)} endpoints):")
for api in apis:
print(f" [{api['type']}] {api.get('name')} - {api.get('method', '')}{api.get('path', api.get('route', ''))}")
return apis
Step 5: API Version and Shadow API Detection
defdetect_shadow_and_zombie_apis(discovered_endpoints, documented_endpoints):
"""Compare discovered APIs against documented inventory."""# Normalize endpoints for comparisondefnormalize(ep):
ep = re.sub(r'/v\d+/', '/vX/', ep)
ep = re.sub(r'/\d+', '/{id}', ep)
return ep.lower().rstrip('/')
documented_normalized = {normalize(ep) for ep in documented_endpoints}
shadow_apis = [] # Discovered but not documented
zombie_apis = [] # Old versions still accessiblefor ep in discovered_endpoints:
normalized = normalize(ep["url"])
if normalized notin documented_normalized:
# Check if it is an old version of a documented APIif re.search(r'/v[0-9]+/', ep["url"]):
zombie_apis.append(ep)
else:
shadow_apis.append(ep)
print(f"\nShadow APIs (undocumented): {len(shadow_apis)}")
for api in shadow_apis:
print(f" [SHADOW] {api['url']} -> {api['status']}")
print(f"\nZombie APIs (deprecated versions): {len(zombie_apis)}")
for api in zombie_apis:
print(f" [ZOMBIE] {api['url']} -> {api['status']}")
# Check if zombie APIs lack security controlsfor api in zombie_apis:
resp = requests.get(api["url"], timeout=5)
if resp.status_code notin (401, 403):
print(f" [CRITICAL] Zombie API accessible without auth: {api['url']}")
return shadow_apis, zombie_apis
Key Concepts
Term
Definition
Shadow API
An API deployed by a development team without going through the official API management or security review process
Zombie API
A deprecated or old API version that remains accessible and running but is no longer maintained or monitored
API Inventory
A comprehensive catalog of all APIs in an organization including endpoint URLs, owners, versions, authentication methods, and data classifications
Improper Inventory Management
OWASP API9:2023 - failure to maintain an accurate API inventory, leading to unmonitored and unprotected API endpoints
Attack Surface
The total set of API endpoints, methods, and parameters that an attacker can potentially interact with
API Sprawl
The uncontrolled proliferation of APIs in an organization, often resulting from microservice adoption without centralized governance
Tools & Systems
Amass: OWASP tool for attack surface mapping through DNS enumeration, web scraping, and API discovery
httpx: Fast HTTP probing tool for validating discovered domains and identifying live API endpoints
nuclei: Template-based scanner for detecting exposed API documentation, debug endpoints, and misconfigured services
Swagger UI Detector: Tool for finding exposed Swagger/OpenAPI documentation endpoints across the organization
Akto: API security platform that discovers APIs through traffic analysis and maintains an automated inventory
Common Scenarios
Scenario: Enterprise API Attack Surface Assessment
Context: A large enterprise has 200+ development teams using microservices. The security team suspects many undocumented APIs are exposed to the internet. A comprehensive API inventory is needed for a security audit.