8ed5311b8e
The image ships 15 tools (jwt_tool, interactsh-client, arjun, dirsearch, gospider, wafw00f, retire, eslint, jshint, js-beautify, JS-Snooper, jsniper.sh, vulnx, ncat, uv) that the always-loaded skills never name with usage guidance — agents could discover them via the environment catalog but had no when/how. Add concise mentions in the natural home for each: jwt_tool in the JWT skill, interactsh-client in the OAST sections of SSRF/XXE/RCE, arjun in IDOR recon, dirsearch as the broad alternate in the ffuf skill, gospider + the JS scrapers in katana, wafw00f next to httpx, retire/eslint/jshint/js-beautify as a new JavaScript-Side Coverage block in the SAST playbook, uv in python, vulnx in the deep scan-mode CVE bullet, ncat in a new RCE Tooling block. Audit also turned up three real breakages along the way: - jwt_tool's shebang resolves to /usr/bin/python3 but its dependencies live in /app/.venv, so every invocation died with ModuleNotFoundError: ratelimit. Replace the bare symlink with a wrapper that execs /app/.venv/bin/python against the real script. - dirsearch's pipx venv ended up with setuptools 82, which dropped pkg_resources — startup failed before parsing args. Pin the inject to setuptools<81. - ESLint's --no-eslintrc flag was removed in v9; the surviving --no-config-lookup covers it. Drop the dead flag from the SAST command block. Also corrected the JS-Snooper / jsniper.sh entry in katana.md — both take a bare domain and run their own JS discovery internally, not the JS URLs Katana already harvested.
101 lines
3.6 KiB
Markdown
101 lines
3.6 KiB
Markdown
---
|
|
name: python
|
|
description: Run Python through exec_command in the SDK sandbox. Use the image-baked caido_api module for Caido proxy automation from Python scripts.
|
|
---
|
|
|
|
# Python In The Sandbox
|
|
|
|
Use `exec_command` for Python. There is no separate Strix Python executor.
|
|
|
|
Prefer writing reusable scripts to `/workspace/scratch/<name>.py` and
|
|
running them with `python3 /workspace/scratch/<name>.py`. For short
|
|
one-off transformations, `python3 -c` or a small here-document is fine.
|
|
|
|
The `shell` parameter on `exec_command` is for swapping POSIX shells
|
|
(`bash`/`zsh`/`sh`), not for picking interpreters. Put the interpreter
|
|
invocation in `cmd` instead: `cmd="python3 -c '...'"`, not
|
|
`shell=python3, cmd="..."`. The `shell=<interpreter>` shortcut breaks
|
|
in subtle ways — `python3` works only with `login=False` (because the
|
|
SDK adds `-l`/`-i`), and other interpreters (`node`, `ruby`, `perl`)
|
|
take `-e` not `-c` so they fail even with `login=False`.
|
|
|
|
## Proxy Automation From Python
|
|
|
|
The sandbox image includes an installed `caido_api` module. Import it
|
|
explicitly when Python code needs Caido traffic or replay access:
|
|
|
|
```python
|
|
from caido_api import (
|
|
list_requests,
|
|
list_sitemap,
|
|
repeat_request,
|
|
scope_rules,
|
|
view_request,
|
|
view_sitemap_entry,
|
|
)
|
|
```
|
|
|
|
All helpers are async. Use them inside `asyncio.run(...)` or an async
|
|
function:
|
|
|
|
```python
|
|
import asyncio
|
|
|
|
from caido_api import list_requests, view_request
|
|
|
|
|
|
async def main():
|
|
posts = await list_requests(
|
|
httpql_filter='req.method.eq:"POST" AND req.path.cont:"/api/"',
|
|
first=50,
|
|
)
|
|
candidates = []
|
|
for edge in posts.edges:
|
|
request_id = edge.node.request.id
|
|
body = await view_request(request_id, part="request")
|
|
raw = body.request.raw.decode("utf-8", errors="replace")
|
|
if "id=" in raw or "user=" in raw:
|
|
candidates.append(request_id)
|
|
|
|
print(f"{len(candidates)} candidates")
|
|
print(candidates[:10])
|
|
|
|
|
|
asyncio.run(main())
|
|
```
|
|
|
|
Available helpers:
|
|
|
|
- `list_requests(httpql_filter=, first=50, after=, sort_by=, sort_order=, scope_id=)` returns a cursor-paginated Caido SDK `Connection`.
|
|
- `view_request(request_id, part="request")` returns a Caido SDK request object with raw request/response bytes.
|
|
- `repeat_request(request_id, modifications={...})` replays a captured request after modifying `url`, `params`, `headers`, `body`, or `cookies`.
|
|
- `list_sitemap(scope_id=, parent_id=, depth="DIRECT", page=1)` walks Caido's request-tree view of the discovered surface. Omit `parent_id` for root domains; pass an entry id with `depth="DIRECT"` or `"ALL"` to drill in.
|
|
- `view_sitemap_entry(entry_id)` returns one entry plus its 30 most recent related requests.
|
|
- `scope_rules(action, allowlist=, denylist=, scope_id=, scope_name=)` manages Caido scopes.
|
|
|
|
For one-off arbitrary requests (e.g. probing a fresh endpoint, hitting an
|
|
external API), use `exec_command` with `curl` / `httpx` / `requests`. The
|
|
sandbox's `HTTP_PROXY` env routes all such traffic through Caido
|
|
automatically, so it shows up in `list_requests` and you can use
|
|
`repeat_request` to replay-and-modify any of it.
|
|
|
|
## Workflow
|
|
|
|
For iterative exploit work, put code in a file:
|
|
|
|
```text
|
|
1. Create or edit `/workspace/scratch/exploit.py` with `apply_patch`.
|
|
2. Run it with `exec_command`: `python3 /workspace/scratch/exploit.py`.
|
|
3. Edit and rerun until the proof-of-concept is reliable.
|
|
```
|
|
|
|
## Installing extra packages
|
|
|
|
The sandbox's Python lives in `/app/.venv`. To add a one-off dependency
|
|
for an exploit script, use `uv` (already in the image and much faster
|
|
than pip):
|
|
|
|
```bash
|
|
uv pip install --python /app/.venv/bin/python <package>
|
|
```
|