Files
strix/strix/skills/tooling/python.md
T
0xallam 8ed5311b8e Surface the previously-undocumented sandbox tools and unbreak two of them
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.
2026-05-25 22:02:15 -07:00

3.6 KiB

name, description
name description
python 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:

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:

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:

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):

uv pip install --python /app/.venv/bin/python <package>