Imported from razor-ai/openhunt (
openhunt/skills/caido-mode/SKILL.md). Install upstream withnpx skills add razor-ai/openhunt --skill caido-mode. Copyright stays with the author.
Caido Mode Skill
Provenance & version compatibility. This is a modified version of the publicly available
caido-modeskill, adapted for OpenHunt and pinned to Caido + Caido-CLI 0.57.0 specifically. Caido's SDK/GraphQL surface changes between releases (e.g. the hand-written 0.57 replay path inlib/output.ts); on other Caido versions some commands may need adjustment.
Overview
Full-coverage CLI for Caido API, built on official @caido/sdk-client package. Covers:
- HTTP History - Search, retrieve, replay, edit requests with HTTPQL
- Replay & Sessions - Sessions, collections, entries, replay-tab lookup, fuzzing
- Scopes - Create and manage testing scopes (allowlist/denylist patterns)
- Filter Presets - Save and reuse HTTPQL filter presets
- Environments - Store test variables (victim IDs, tokens, etc.)
- Findings - Create, list, update security findings
- Tasks - Monitor and cancel background tasks
- Projects - Switch between testing projects
- Hosted Files - Manage files served by Caido
- Intercept - Enable/disable request interception programmatically
- Plugins - List installed plugins
- Export - Convert requests to curl commands for PoCs
- Health - Check Caido instance status
All traffic goes through Caido, appears in UI for further analysis.
Why This Model?
Cookies and auth tokens can be huge - session cookies, JWTs, CSRF tokens easily 1-2KB. Rather than manually copy-pasting:
- Find organic request in Caido HTTP history that already has valid auth
- Use
editto modify what you need (path, method, body) keeping all auth headers intact - Send it - response comes back with full context preserved
Authentication Setup
Setup (One-Time)
- Open Dashboard → Developer → Personal Access Tokens
- Create new token
- Run:
npx -y tsx ${CLAUDE_PLUGIN_ROOT}/skills/caido-mode/caido-client.ts setup <your-pat>
# Non-default Caido instance
npx -y tsx ${CLAUDE_PLUGIN_ROOT}/skills/caido-mode/caido-client.ts setup <pat> http://192.168.1.100:8080
# Or set env var instead
export CAIDO_PAT=caido_xxxxx
setup command validates PAT via SDK (which exchanges it for access token), then saves both PAT and cached access token to ~/.claude/config/secrets.json. Subsequent runs load cached token directly, skipping PAT exchange. Valid cached token works even when PAT absent; expired cached token errors with re-setup instructions.
Check Status
npx -y tsx ${CLAUDE_PLUGIN_ROOT}/skills/caido-mode/caido-client.ts auth-status
auth-status reports authMode (pat / cached-token), hasPat, cachedTokenExpiresAt, cachedTokenValid.
How Auth Works
SDK uses device code flow internally — PAT auto-approves it and receives access token + refresh token. Custom SecretsTokenCache (implementing SDK TokenCache interface) persists tokens to secrets.json so they survive across CLI invocations.
Auth resolution: CAIDO_PAT env var → secrets.json PAT → valid cached access token → error with setup instructions
CLI Tool
Located at ${CLAUDE_PLUGIN_ROOT}/skills/caido-mode/caido-client.ts. All commands output JSON.
HTTP History & Testing Commands
search - Search HTTP history with HTTPQL
npx -y tsx caido-client.ts search 'req.method.eq:"POST" AND resp.code.eq:200'
npx -y tsx caido-client.ts search 'req.host.cont:"api"' --limit 50
npx -y tsx caido-client.ts search 'req.host.cont:"api"' --desc --limit 10 # newest first by request ID
npx -y tsx caido-client.ts search 'req.path.cont:"/admin"' --ids-only
npx -y tsx caido-client.ts search 'resp.raw.cont:"password"' --after <cursor>
--desc (alias --latest) sorts newest first.
recent - Get recent requests
npx -y tsx caido-client.ts recent
npx -y tsx caido-client.ts recent --limit 50
get / get-response - Retrieve full details
npx -y tsx caido-client.ts get <request-id>
npx -y tsx caido-client.ts get <request-id> --headers-only
npx -y tsx caido-client.ts get-response <request-id>
npx -y tsx caido-client.ts get-response <request-id> --compact
edit - Edit and replay (KEY FEATURE)
Modifies existing request while preserving all cookies/auth headers:
# Change path (IDOR testing)
npx -y tsx caido-client.ts edit <id> --path /api/user/999
# Change method and add body
npx -y tsx caido-client.ts edit <id> --method POST --body '{"admin":true}'
# Add/remove headers
npx -y tsx caido-client.ts edit <id> --set-header "X-Forwarded-For: 127.0.0.1"
npx -y tsx caido-client.ts edit <id> --remove-header "X-CSRF-Token"
# Find/replace text anywhere in request
npx -y tsx caido-client.ts edit <id> --replace "user123:::user456"
# Combine multiple edits
npx -y tsx caido-client.ts edit <id> --method PUT --path /api/admin --body '{"role":"admin"}' --compact
# Reuse an existing replay tab while iterating (NOT for evidence — see Replay Sessions)
npx -y tsx caido-client.ts edit <id> --path /api/user/1001 --session <session-id> --compact
| Option | Description |
|---|---|
--method <METHOD> |
Change HTTP method |
--path <path> |
Change request path |
--set-header <Name: Value> |
Add or replace a header (repeatable) |
--remove-header <Name> |
Remove a header (repeatable) |
--body <content> |
Set request body (auto-updates Content-Length) |
--replace <from>:::<to> |
Find/replace text anywhere in request (repeatable) |
--session <id> |
Reuse existing replay session instead of new tab (iterative testing only) |
--collection <id> |
Put a newly created replay session in a collection |
--sni <host> |
Override TLS SNI |
--connect-host <host> |
Connect to a different host, keep HTTP request intact |
--connect-port <port> |
Connect to a different port |
--connect-tls / --connect-no-tls |
Force TLS / plaintext on the connection |
replay / send-raw - Send requests
--raw accepts: a string with \r\n escapes (auto-normalized to real CRLF bytes), @file to read from disk, or - to read from stdin. No $'...' quoting needed — escapes are normalized.
# Replay as-is
npx -y tsx caido-client.ts replay <request-id>
# Replay with custom raw (escapes normalized)
npx -y tsx caido-client.ts replay <id> --raw 'GET /modified HTTP/1.1\r\nHost: example.com\r\n\r\n'
# Send completely custom request
npx -y tsx caido-client.ts send-raw --host example.com --port 443 --tls --raw 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'
# Raw from file / stdin; name the replay tab
npx -y tsx caido-client.ts send-raw --host example.com --raw @request.txt --name "G /api/check"
cat request.txt | npx -y tsx caido-client.ts send-raw --host example.com --raw -
# Connection override (vhost / upstream routing): keep request Host + SNI, connect elsewhere
npx -y tsx caido-client.ts replay <id> --connect-host 10.0.0.5 --connect-port 8443 --sni example.com
Connection overrides on replay/send-raw/edit: --sni, --connect-host, --connect-port, --connect-tls, --connect-no-tls. Add session to a collection with --collection <id>; name a send-raw tab with --name.
export-curl - Final PoC / Reporting / Handoff Only
npx -y tsx caido-client.ts export-curl <request-id>
Use only when you need a standalone reproduction command for final PoC, reporting, handoff, or operator debugging.
Replay Tab Lookup
Work from an already-open Caido replay tab via its active entry.
npx -y tsx caido-client.ts get-session <id-or-name> --compact
npx -y tsx caido-client.ts replay-entries <id-or-name> --limit 20
npx -y tsx caido-client.ts replay-entries <id-or-name> --raw --compact
npx -y tsx caido-client.ts edit-session <id-or-name> --body '{"test":true}' --compact
session-entries = alias for replay-entries. Sessions resolve by ID or name.
⚠ Evidence: edit-session (and edit --session) send into an existing session → may produce ghost entries (not persisted; Caido UI shows "This resource does not exist"). Iterative testing only. For durable evidence use atomic replay — see Replay Sessions below.
Replay Sessions & Collections
Sessions
# Create replay session from an existing request
npx -y tsx caido-client.ts create-session <request-id>
npx -y tsx caido-client.ts create-session <request-id> --collection <collection-id>
# ALWAYS rename sessions for easy identification in Caido UI
npx -y tsx caido-client.ts rename-session <session-id> "idor-user-profile"
# Move a session to a collection
npx -y tsx caido-client.ts move-session <session-id> <collection-id>
# List all replay sessions
npx -y tsx caido-client.ts replay-sessions
npx -y tsx caido-client.ts replay-sessions --limit 50
# Delete replay sessions
npx -y tsx caido-client.ts delete-sessions <session-id-1>,<session-id-2>
Evidence collection (durable): only atomic replay writes entries persisted to Caido's DB. Workflow: replay <id> --collection <coll-id> (or replay <id> → move-session <sid> <coll-id>) → rename-session <sid> "01 - ...". Do NOT use edit-session/edit/create-session-then-resend for evidence — ghost entries (UI: "This resource does not exist"). Always verify the entry renders in the Caido UI. See caido-replay skill + CLAUDE.md Applied Learning.
Collections
Organize replay sessions into collections:
# List replay collections
npx -y tsx caido-client.ts replay-collections
npx -y tsx caido-client.ts replay-collections --limit 50
# Create a collection
npx -y tsx caido-client.ts create-collection "IDOR Testing"
# Rename a collection
npx -y tsx caido-client.ts rename-collection <collection-id> "Auth Bypass Tests"
# Delete a collection
npx -y tsx caido-client.ts delete-collection <collection-id>
Fuzzing
# Create automate session for fuzzing
npx -y tsx caido-client.ts create-automate-session <request-id>
# Start fuzzing (configure payloads and markers in Caido UI first)
npx -y tsx caido-client.ts fuzz <session-id>
Scope Management
Define what's in scope for testing. Uses glob patterns.
# List all scopes
npx -y tsx caido-client.ts scopes
# Create scope with allowlist and denylist
npx -y tsx caido-client.ts create-scope "Target Corp" --allow "*.target.com,*.target.io" --deny "*.cdn.target.com"
# Update scope
npx -y tsx caido-client.ts update-scope <scope-id> --allow "*.target.com,*.api.target.com"
# Delete scope
npx -y tsx caido-client.ts delete-scope <scope-id>
Glob patterns: *.example.com matches any subdomain of example.com.
Filter Presets
Save frequently used HTTPQL queries as named presets.
# List saved filters
npx -y tsx caido-client.ts filters
# Create filter preset
npx -y tsx caido-client.ts create-filter "API Errors" --query 'req.path.cont:"/api/" AND resp.code.gte:400'
npx -y tsx caido-client.ts create-filter "Auth Endpoints" --query 'req.path.regex:"/(login|auth|oauth)/"' --alias "auth"
# Update filter
npx -y tsx caido-client.ts update-filter <filter-id> --query 'req.path.cont:"/api/" AND resp.code.gte:500'
# Delete filter
npx -y tsx caido-client.ts delete-filter <filter-id>
Environment Variables
Store testing variables persisting across sessions. Great for IDOR testing with multiple user IDs.
# List environments
npx -y tsx caido-client.ts envs
# Create environment
npx -y tsx caido-client.ts create-env "IDOR-Test"
# Set variables
npx -y tsx caido-client.ts env-set <env-id> victim_user_id "user_456"
npx -y tsx caido-client.ts env-set <env-id> attacker_token "eyJhbG..."
# Select active environment
npx -y tsx caido-client.ts select-env <env-id>
# Deselect environment
npx -y tsx caido-client.ts select-env
# Delete environment
npx -y tsx caido-client.ts delete-env <env-id>
Findings
Create, list, update security findings. Shows up in Caido Findings tab. (Caido SDK term: "findings"; OpenHunt passive-layer prose term: "detections".)
# List all findings
npx -y tsx caido-client.ts findings
npx -y tsx caido-client.ts findings --limit 50
# Get a specific finding
npx -y tsx caido-client.ts get-finding <finding-id>
# Create finding linked to a request
npx -y tsx caido-client.ts create-finding <request-id> \
--title "IDOR in user profile endpoint" \
--description "Can access other users' profiles by changing ID parameter" \
--reporter "rez0"
# With deduplication key (prevents duplicates)
npx -y tsx caido-client.ts create-finding <request-id> \
--title "Auth bypass on /admin" \
--dedupe-key "admin-auth-bypass"
# Update finding
npx -y tsx caido-client.ts update-finding <finding-id> \
--title "Updated title" \
--description "Updated description"
Tasks
Monitor and cancel background tasks (imports, exports, etc.).
# List all tasks
npx -y tsx caido-client.ts tasks
# Cancel a running task
npx -y tsx caido-client.ts cancel-task <task-id>
Project Management
# List all projects
npx -y tsx caido-client.ts projects
# Switch active project
npx -y tsx caido-client.ts select-project <project-id>
Hosted Files
# List hosted files
npx -y tsx caido-client.ts hosted-files
# Delete hosted file
npx -y tsx caido-client.ts delete-hosted-file <file-id>
Intercept Control
# Check intercept status
npx -y tsx caido-client.ts intercept-status
# Enable/disable interception
npx -y tsx caido-client.ts intercept-enable
npx -y tsx caido-client.ts intercept-disable
Info, Health & Plugins
# Current user info
npx -y tsx caido-client.ts viewer
# List installed plugins
npx -y tsx caido-client.ts plugins
# Check Caido instance health (version, ready state)
npx -y tsx caido-client.ts health
Output Control
Works with get, get-response, replay, send-raw, edit, get-session, replay-entries, edit-session:
| Flag | Description |
|---|---|
--max-body <n> |
Max response body lines (default: 200, 0=unlimited) |
--max-body-chars <n> |
Max body chars (default: 5000, 0=unlimited) |
--no-request |
Skip request raw in output |
--headers-only |
Only HTTP headers, no body |
--compact |
Shorthand: --no-request --max-body 50 --max-body-chars 5000 |
HTTPQL Quick Reference
See references/caido-overview.md for full HTTPQL field/operator reference.
CRITICAL: String values MUST be quoted. Integer values NOT quoted.
CRITICAL: No NOT keyword exists. Use negated operators: ne, ncont, nlike, nregex. Wrong: NOT req.path.cont:"/admin". Right: req.path.ncont:"/admin".
req.method.eq:"POST" AND resp.code.eq:200
req.host.cont:"api" OR req.path.cont:"/api/"
"password" OR "secret" OR "api_key"
resp.code.gte:400 AND resp.code.lt:500
resp.len.gt:100000
req.path.regex:"/(login|auth|signin|oauth)/"
req.path.ncont:"/static" AND req.method.ne:"OPTIONS"
source:"replay" OR source:"automate"
String operators: eq, ne, cont, ncont, like, nlike, regex, nregex
Integer operators: eq, ne, gt, gte, lt, lte
Boolean operators: eq, ne
Logical: AND, OR, parentheses for grouping
Workflow Examples
1. IDOR Testing (Primary Pattern)
# Find authenticated request
npx -y tsx caido-client.ts search 'req.path.cont:"/api/user"' --limit 10
# Create scope
npx -y tsx caido-client.ts create-scope "IDOR-Test" --allow "*.target.com"
# Create environment for test data
npx -y tsx caido-client.ts create-env "IDOR-Test"
npx -y tsx caido-client.ts env-set <env-id> victim_id "user_999"
# Test IDOR by changing user ID
npx -y tsx caido-client.ts edit <request-id> --path /api/user/999
# Mark as finding if it works
npx -y tsx caido-client.ts create-finding <request-id> --title "IDOR on /api/user/:id"
# Export curl for PoC
npx -y tsx caido-client.ts export-curl <request-id>
2. Privilege Escalation Testing
npx -y tsx caido-client.ts search 'req.path.cont:"/admin"' --limit 10
npx -y tsx caido-client.ts edit <id> --path /api/admin/users --method GET
npx -y tsx caido-client.ts edit <id> --method POST --body '{"role":"admin"}'
3. Header Bypass Testing
npx -y tsx caido-client.ts edit <id> --set-header "X-Forwarded-For: 127.0.0.1"
npx -y tsx caido-client.ts edit <id> --set-header "X-Original-URL: /admin"
npx -y tsx caido-client.ts edit <id> --remove-header "X-CSRF-Token"
4. Fuzzing with Automate
npx -y tsx caido-client.ts create-automate-session <request-id>
# Configure payload markers and wordlists in Caido UI
npx -y tsx caido-client.ts fuzz <session-id>
5. Filter + Analyze Pattern
npx -y tsx caido-client.ts create-filter "API 4xx" --query 'req.path.cont:"/api/" AND resp.code.gte:400 AND resp.code.lt:500'
npx -y tsx caido-client.ts create-filter "Sensitive Data" --query '"password" OR "secret" OR "api_key" OR "token"'
npx -y tsx caido-client.ts search 'preset:"API 4xx"' --limit 20
6. Durable Evidence Collection
# Atomic replay into a collection, then name the entry — durable in Caido DB
npx -y tsx caido-client.ts create-collection "IDOR /api/user"
npx -y tsx caido-client.ts replay <request-id> --collection <collection-id>
npx -y tsx caido-client.ts rename-session <session-id> "01 - baseline 200"
Instructions for Claude
- PREFER
editOVERreplay --raw- preserves cookies/auth automatically - Workflow: Search → find request with valid auth → use that ID for all tests via
edit - Don't dump raw requests into context - use
--compactor--headers-onlywhen exploring - Always check auth first:
healthto verify connection, thenrecent --limit 1 - ALWAYS NAME REPLAY TABS:
rename-session <id> "idor-user-profile" - Create findings for anything interesting - they show up in Caido Findings tab
- Use
export-curlonly for final PoC, reporting, handoff, or operator debugging - Evidence = atomic
replayonly -edit/edit-sessionreusing a session produce ghost entries; collect durable evidence withreplay [--collection]→rename-session - Create filter presets for recurring searches to save typing
- Use environments to store test data (victim IDs, tokens, etc.)
- NEVER use
NOTin HTTPQL - it doesn't exist; usene,ncont,nlike,nregex - Output is JSON - parse response fields as needed
Performance & Context Optimization
search/recentomitrawfield (~200 bytes per request, safe for 100+)getfetchesraw(~5-20KB per request, fetch only what you need)- Use
--limitaggressively (start with 5-10) - Use
--compactflag for quick exploration - Filter server-side with HTTPQL, not client-side
Error Handling
- Auth errors: Run
npx -y tsx caido-client.ts auth-statusto check, re-setup withnpx -y tsx caido-client.ts setup <pat> - Connection refused: Caido not running →
npx -y tsx caido-client.ts health - InstanceNotReadyError: Caido is starting up, wait and retry