# Recon

> Systematically discover alternative endpoints, bypasses, and undocumented access paths on a target platform. Use after the normal flow works to find simpler or more efficient approaches.

- Skill: `franco-bianco/recon` (Agent Skill)
- Install (CLI): `npx skillmds@latest add franco-bianco/recon`
- Raw SKILL.md: https://api.skillmd.com/api/skills/franco-bianco/recon/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: franco-bianco (https://skillmd.com/u/franco-bianco)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/franco-bianco/recon

---


# Recon

Systematically discover alternative endpoints, bypasses, and undocumented access paths. Use this after you have a working flow (via browser-navigate + network-debug) and want to find simpler or more efficient approaches.

## 1. Map the Attack Surface

### Subdomain enumeration

- **Certificate Transparency** — `https://crt.sh/?q=%25.example.com&output=json` lists all issued certificates
- **Reverse DNS** — `dig -x <IP>` to find co-hosted domains on the same server
- **DNS records** — `dig example.com ANY` for MX, TXT, CNAME revealing internal hosts
- **Response headers** — `X-Served-By`, `X-Backend-Server`, `Via` in captured traffic
- **JavaScript bundles** — grep captured JS for hardcoded URLs and subdomains
- **CORS headers** — `Access-Control-Allow-Origin` reveals sibling domains

### Path enumeration

- `robots.txt` — disallowed paths often point to interesting endpoints
- `sitemap.xml` — URL structure and available pages
- **OpenAPI/Swagger** — `/swagger.json`, `/openapi.json`, `/api-docs`, `/v1/docs`
- **GraphQL** — `/graphql`, `/graphiql`. Run introspection query if found
- **Health/status** — `/health`, `/status`, `/version`, `/info`

### Tech stack identification

- **Response headers** — `X-Powered-By`, `Server`, `X-Cache`
- **Cookie names** — `JSESSIONID` (Java), `PHPSESSID` (PHP), `connect.sid` (Express)
- **Error pages** — trigger 404/500 to identify framework
- **HTML source** — `__NEXT_DATA__` (Next.js), `__NUXT__` (Nuxt), generator meta tags

## 2. Alternative Access Surfaces

- **Mobile APIs** — proxy a phone, compare mobile vs desktop responses
- **Mobile web** — `m.example.com` or responsive variants
- **Export/bulk endpoints** — `/export`, `/download`, `?format=csv`
- **Print views** — `/print`, `?print=true`
- **RSS/Atom** — `/feed`, `/rss`, `/atom.xml`
- **Developer/partner APIs** — `developer.example.com`, `/developers`

## 3. API Version and Format Exploration

- **Version probing** — try v1, v2, v3; check for version headers (`API-Version`, `Accept-Version`)
- **Format negotiation** — `Accept: application/json` on HTML pages, JSONP via `?callback=x`
- **GraphQL alongside REST** — same data, different access control or rate limits
- **Content-Type alternatives** — form-encoded vs JSON POST bodies may have different validation

## 4. Embedded Data Extraction

Pages often embed all their data in HTML, avoiding the need for separate API calls.

### In-browser extraction

```javascript
// JSON data blocks
evaluate_script(function: "() => { return [...document.querySelectorAll('script[type=\"application/json\"]')].map(s => s.textContent.substring(0, 200)) }")

// Linked data
evaluate_script(function: "() => { return [...document.querySelectorAll('script[type=\"application/ld+json\"]')].map(s => JSON.parse(s.textContent)) }")

// Inline JSON assignments
evaluate_script(function: "() => { return [...document.querySelectorAll('script:not([src])')].map(s => s.textContent).filter(t => t.includes('window.__') || t.includes('initialState') || t.includes('pageData')).map(t => t.substring(0, 300)) }")
```

### From captured traffic

- **Script tags** — `<script type="application/json">` and `<script type="application/ld+json">` in HTML responses. Use `powhttp_query_body` with JQ expressions to extract.
- **Inline assignments** — `window.__DATA__ = {`, `"sectionPopupData":`, `var initialState =` in script blocks
- **Linked data URLs** — scripts may reference internal API URLs not called during page load

Use `powhttp_get_entry(body_mode: "full")` on HTML page loads to inspect raw source.

## 5. JavaScript Source Analysis

- **Bundle grep** — search for `baseURL`, `apiUrl`, `fetch("`, `axios.create` in JS files
- **Source maps** — append `.map` to JS URLs to get original source
- **Build-time env vars** — `NEXT_PUBLIC_`, `REACT_APP_`, `VUE_APP_` prefixed variables
- **Webpack chunks** — named chunks correspond to features, revealing endpoint patterns

## 6. Platform-Specific Endpoints

- **Next.js** — `/_next/data/<buildId>/<path>.json` returns page data as JSON
- **Nuxt.js** — `/_payload.json` for page data
- **Shopify** — `/products.json`, `/collections.json`, Storefront API
- **WordPress** — `/wp-json/wp/v2/` REST API
- **Elasticsearch** — `/_search`, `/_mapping` if exposed
- **Firebase** — `<project>.firebaseio.com/.json` if rules allow

## 7. Related Site Analysis

- **Same parent company** — shared backends, consistent endpoint patterns
- **Same platform** — one site's patterns apply to all sites on that platform
- **Community resources** — GitHub for unofficial SDKs: `site:github.com "example.com" api`
- **Wayback Machine** — old JS bundles reveal historical endpoints that may still be active
- **CORS headers** — `Access-Control-Allow-Origin` reveals sibling domains

## 8. Auth and Session Shortcuts

### Session inspection

```javascript
// Get all cookies
evaluate_script(function: "() => { return document.cookie }")

// Inspect localStorage keys
evaluate_script(function: "() => { return Object.keys(localStorage) }")

// Get specific localStorage value
evaluate_script(function: "() => { return localStorage.getItem('authToken') }")

// Decode a JWT from a cookie
evaluate_script(function: "() => { const token = document.cookie.split('; ').find(c => c.startsWith('jwt=')); if (!token) return null; const payload = token.split('.')[1]; return JSON.parse(atob(payload.split('=')[0].replace(/-/g, '+').replace(/_/g, '/'))) }")
```

### Session lifecycle

- **Minimal cookie set** — test subsets to find minimum required cookies. Use `powhttp_get_entry(include_headers: true)` to check which cookies the server actually reads.
- **Token reuse** — web auth tokens on mobile endpoints and vice versa
- **JWT inspection** — decode expiry (`exp` field), understand refresh lifecycle
- **Silent refresh** — GET homepage may renew session without re-auth
- **Cookie dependency mapping** — which cookies the server reads vs ignores
- **Unauthorized detection** — some sites signal expiry by clearing cookies (`Set-Cookie` with past expiration) rather than returning error status

### Endpoint discovery from known patterns

- **URL pattern inference** — if `/listings/getListings` exists, try `/sales/getSales`, `/orders/getOrders`
- **Query parameter exploration** — test `pageSize`, `limit`, `offset`, `sort`, `dateFrom`, `dateTo`, `status`, `filter`
- **Larger page sizes** — default pagination is often conservative (20-50). Test `pageSize=500` or `pageSize=1000`.

### Response schema analysis

- **Abbreviated field names** — minified APIs use short keys (`"i"` for ID, `"n"` for name). Use `powhttp_query_body` to extract samples and infer meaning.
- **Nullable fields** — compare multiple responses with `powhttp_describe_endpoint` to see field consistency
- **Enum collection** — `powhttp_query_body` with `deduplicate: true` across a cluster to collect all status/type values
- **Nested pagination** — check top-level structure for wrapper objects (`{"items": [...], "total": 500, "page": 1}`)

### Keys in source

- `apiKey`, `token`, `client_id` in JS bundles or HTML
- `Geo/locale headers` — `X-Forwarded-For`, `Accept-Language` effects on responses

