Inspect sandbox
Plug-and-play skills for Agents that give actionable steps, tool integrations, and verifiable outputs. Includes a sandbox inspector for remote running environments with automatic HTML reports of same, Mermaid diagrams, and PDF export.
npx -y skills add rondomondo/agent-skills-beta --skill inspect-sandboxAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Inspects a Linux container or sandbox environment and produces a structured HTML report and downloadable PDF covering filesystem mounts, process security context, network configuration, available runtimes, and running processes. Use this skill whenever the user asks to inspect, audit, probe, or explore a sandbox or container environment -- including questions like "what tools are available here?", "what network access does this have?", "what's the security context?", "show me what's mounted", or "give me an environment report". Also trigger when the user asks what capabilities, runtimes, or filesystem layout the current environment has.
SKILL.md
16.1 KB, as published. Nobody here has run it
Sandbox Inspector
Automated environment inspection that parses system state into a self-contained HTML viewer with collapsible sections, category filters, and rendered Mermaid diagrams. When running inside the Claude sandbox, the full output is packaged into a downloadable zip that the user can run locally with a single command. A multi-page landscape A4 PDF of all text sections is also rendered via Playwright and presented inline in the chat client.
MANDATORY: Always Use make inspect
make inspect MUST always be run. Never call sandbox_inspect.sh or generate_diagrams.py directly. The make inspect target is the only supported entry point -- it orchestrates the full pipeline in the correct order:
- Stop: Kills any stale server
- Inspection: Runs
sandbox_inspect.sh-> timestampedoutput/sandbox/report_*.txt+latestsymlink - Diagrams: Runs
generate_diagrams.py->output/sandbox/diagram_*.md+diagrams.json - Serve + Open: Starts the HTTP server and opens
inspector.htmlin the default browser
Calling scripts individually will produce incomplete or inconsistent output. make inspect is the contract -- use it.
Production Workflow
1. Run the Inspection
make inspect
This is the only step needed. The full pipeline runs automatically.
2. Post-inspection: Sandbox Bundle (IS_SANDBOX=yes)
After make inspect completes, check the environment:
echo "${IS_SANDBOX:-no}"
If IS_SANDBOX=yes, the HTML viewer cannot be served directly -- there is no browser. Instead, perform steps 3a-3e to build a downloadable zip the user can run locally.
3a. Render Mermaid diagrams
generate_diagrams.py writes .md files containing fenced Mermaid blocks. These must be rendered to SVG before packaging. In the sandbox, use mmdc directly (Docker is unavailable):
cat > /tmp/puppeteer-config.json << 'EOF'
{
"executablePath": "/opt/pw-browsers/chromium-1194/chrome-linux/chrome",
"args": ["--no-sandbox", "--disable-setuid-sandbox"]
}
EOF
for md in output/sandbox/diagram_*.md; do
base="${md%.md}"
mmdc -i "$md" -o "${base}.svg" --puppeteerConfigFile /tmp/puppeteer-config.json
done
mmdc produces files named diagram_<key>-1.svg (one per diagram block). generate_diagrams.py detects this naming automatically -- if the mmdc output files exist on disk it uses diagram_<key>-1.svg in diagrams.json; if the Docker wrapper naming (diagram_<key>.svg-1.svg) is found instead it uses that. This means rendering can happen before or after the diagrams step without manual intervention.
If Chromium is not at the expected path:
find /opt/pw-browsers -name "chrome" | grep -v headless | head -1
3b. Render PDF
Run screenshot_report.py from the skill working directory. It patches inspector.html to inline all data (bypassing fetch()), stubs out mermaid, loads it via file:// in Playwright/Chromium, then renders all text sections as a single multi-page landscape A4 PDF.
python3 scripts/screenshot_report.py --out-dir output/sandbox
This produces output/sandbox/sandbox-report.pdf -- one A4 landscape page per CSS page-break, covering all five text sections (filesystem, security, network, processes, runtime). The diagrams tab is intentionally excluded: its Mermaid SVGs are built for interactive pan/zoom and paginate badly in print.
Why file:// + inline data? Playwright's Chromium sandbox blocks loopback connections (ERR_SOCKET_NOT_CONNECTED), so an HTTP server on localhost won't work. The script patches inspector.html with all report data inlined and a fetch() interceptor, loads it as file://, renders the PDF, then deletes the patched file.
Optional args:
--width 1400-- viewport width in px before PDF scaling (default: 1400)
If Chromium is not found at the default path (/opt/pw-browsers/chromium-1194/chrome-linux/chrome), the script auto-detects it. Manual fallback:
find /opt/pw-browsers -name "chrome" | grep -v headless | head -1
3c. Create serve.sh
Write a launcher script to the output/sandbox/ working directory (it will be promoted to the zip root in step 3e):
cat > output/sandbox/serve.sh << 'SCRIPT'
#!/usr/bin/env bash
# serve.sh -- Start a local HTTP server to view the sandbox inspection report
# Usage: ./serve.sh [PORT] (default port: 8008)
# Then open: http://localhost:8008/index.html?v=$(date +%s)
set -euo pipefail
PORT="${1:-8008}"
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "Starting sandbox report viewer..."
echo " URL: http://localhost:${PORT}/index.html?v=$(date +%s)"
echo "Press Ctrl+C to stop."
cd "$DIR"
python3 -m http.server "${PORT}"
SCRIPT
chmod +x output/sandbox/serve.sh
3d. Create README.md
Write a README to output/sandbox/ (also promoted to zip root in step 3e). It must cover:
- Full listing of zip contents with a description of each file
- How to run
serve.shand open the viewer (http://localhost:8008/index.html?v=<timestamp>) - Alternative server options:
python3 -m http.server,npx serve, VS Code Live Server - Explicit note that
inspector.htmlmust be served over HTTP -- opening it as afile://URL will not work because it usesfetch()to load report data - Note that
report.txtis available as a plain-text fallback requiring no server
3e. Assemble and zip
SECURITY CHECK -- do this before zipping: Scan output/sandbox/report.txt for any unredacted secrets before packaging. The inspection script masks known patterns, but operator-injected variables with unusual names may slip through. Run:
grep -iE '(KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH|API_|_API|PRIVATE)=' output/sandbox/report.txt \
| grep -v '\*\*\*REDACTED\*\*\*' \
&& echo "WARNING: possible unredacted secrets above -- do NOT zip" \
|| echo "OK: no obvious unredacted secrets found"
If the check prints any lines above the warning, manually redact those lines in report.txt before proceeding. Never zip or share any artifact that contains unmasked credentials.
The zip must follow this exact directory structure:
sandbox-inspection.zip
├-- README.md <- user instructions
├-- index.html <- the HTML viewer
├-- serve.sh <- one-command local server launcher
└-- vendor/
└-- js/
└-- mermaid.min.js <- for rendering the mermaid diagrams
└-- output/
└-- sandbox/
├-- report.txt <- raw plain-text inspection output (copied from latest)
├-- diagrams.json <- diagram manifest consumed by inspector.html
├-- diagram_network.md
├-- diagram_network-1.svg
├-- diagram_mounts.md
├-- diagram_mounts-1.svg
├-- diagram_runtime.md
├-- diagram_runtime-1.svg
├-- diagram_security.md
├-- diagram_security-1.svg
└-- sandbox-report.pdf <- multi-page A4 landscape PDF of all text sections
index.html lives at the zip root and fetches data from the relative path output/sandbox/ -- this is why the hierarchy matters. serve.sh must also be at the root so it serves from the same directory as index.html.
Use a staging directory to assemble the layout, then zip from inside it so no extra path prefix is introduced:
STAGE=/tmp/sandbox-inspection-stage
rm -rf "$STAGE" && mkdir -p "$STAGE/output/sandbox" && mkdir -p "$STAGE/vendor/js"
SRC=output/sandbox
# Promote these to the zip root
cp inspector.html "$STAGE/"
cp inspector.html "$STAGE/index.html"
cp "$SRC/README.md" "$STAGE/"
cp "$SRC/serve.sh" "$STAGE/"
cp vendor/js/mermaid.min.js "$STAGE/vendor/js/"
# Data files stay under output/sandbox/
cp "$(python3 -c "import os,sys; print(os.path.realpath(sys.argv[1]))" "$SRC/latest")" "$STAGE/output/sandbox/report.txt"
cp "$SRC/diagrams.json" "$STAGE/output/sandbox/"
cp "$SRC"/diagram_*.md "$STAGE/output/sandbox/"
cp "$SRC"/diagram_*-1.svg "$STAGE/output/sandbox/"
cp "$SRC/sandbox-report.pdf" "$STAGE/output/sandbox/"
cd "$STAGE"
zip -r /mnt/user-data/outputs/sandbox-inspection.zip .
4. Presenting Results
Always summarise key findings inline regardless of environment: identity & privilege level, Linux capabilities, writable paths, network posture (egress proxy, outbound connectivity), and available runtimes.
In sandbox (IS_SANDBOX=yes):
- Present
sandbox-report.pdfandsandbox-inspection.zipviapresent_files. Tell the user to unzip and run./serve.sh, then openhttp://localhost:8008/index.html?v=<timestamp>(the cache-bustervparam is printed byserve.sh). - Rasterise PDF pages with
pdftoppmandvieweach resulting.jpgso the user gets an immediate visual preview in chat without downloading anything:
# Replace N with the actual last page number (or omit -l entirely to rasterise all pages)
pdftoppm -r 120 -jpeg -f 1 -l N output/sandbox/sandbox-report.pdf /tmp/pdf_preview
# then view each /tmp/pdf_preview-*.jpg
Outside sandbox: use make inspect (which stops any stale server first) to launch inspector.html directly in the default browser.
How the Downloaded Bundle Works
When the user downloads and unzips sandbox-inspection.zip they get a self-contained report package. Here is what each piece does:
index.html -- the interactive viewer. It loads output/sandbox/report.txt and output/sandbox/diagrams.json via fetch(), parses them into collapsible sections, and renders the Mermaid SVGs inline. Starts in light mode. Has a dark/light toggle. Because it relies on fetch() it must be served over HTTP, not opened directly as a file.
serve.sh -- a minimal Python 3 HTTP server launcher. Running ./serve.sh (or ./serve.sh 9090 for a custom port) starts serving from the unzipped directory and prints the URL. Requires only Python 3, which is present on any modern Mac, Linux, or WSL environment.
output/sandbox/report.txt -- the raw plain-text inspection output. Readable in any terminal or text editor without a server. Useful for quick reference or diffing across environments.
output/sandbox/sandbox-report.pdf -- multi-page landscape A4 PDF covering all five text sections. Viewable in any PDF reader without a server. Produced by screenshot_report.py.
output/sandbox/diagrams.json -- manifest that maps diagram keys to their SVG filenames. index.html reads this to know which images to display and where.
output/sandbox/diagram_*.md -- Mermaid source for each diagram. Renderable independently in VS Code (Mermaid Preview extension) or on GitHub.
output/sandbox/diagram_*-1.svg -- pre-rendered SVG diagrams. Displayed inline by the viewer; also openable standalone in any browser.
Available Targets
| Target | Action |
|---|---|
make inspect | Required. Runs the full pipeline: report -> diagrams -> HTML finalization. |
make report | Runs sandbox_inspect.sh -> timestamped output/sandbox/report_*.txt + updates latest symlink. |
make diagrams | Generates Mermaid diagram .md files from the latest report. |
make serve | Starts a local HTTP server at http://localhost:8008 with auto-reload. |
Key Artifacts & Output Tree
output/sandbox/
├-- report_<YYYYMMDD_HHMMSS>.txt # Timestamped raw inspection output
├-- latest -> report_<...>.txt # Symlink to most recent report
├-- diagram_network.md # Mermaid source -- network topology
├-- diagram_mounts.md # Mermaid source -- filesystem topology
├-- diagram_security.md # Mermaid source -- security context
├-- diagram_runtime.md # Mermaid source -- runtime availability
├-- diagram_*-1.svg # Rendered SVG diagrams (mmdc sandbox naming)
├-- diagrams.json # Manifest: key -> {title, md file, svg file}
├-- serve.sh # Staged here before promotion to zip root
├-- README.md # Staged here before promotion to zip root
└-- sandbox-report.pdf # Multi-page A4 landscape PDF (Playwright)
Development & Quality Control
- Formatting:
make format(Black + Isort) - Linting:
make lint(Ruff with auto-fix) - Testing:
make test(Pytest with coverage) - Cleanup:
make clean(removesoutput/sandbox/and venv) - Packaging:
make zip(bundles the skill source for distribution)
Error Handling & Constraints
- Venv missing:
check-venvtarget will error. Runmake installfirst. - Script failures: if
sandbox_inspect.shexits non-zero the pipeline halts -- no partial report. - Port conflicts:
make servedefaults to8008. Override withPORT=9090 make serve. - PDF failures: if
screenshot_report.pyfails, the zip can still be produced without the PDF -- note the failure to the user and present the zip anyway. The PDF is additive; it doesn't block the primary deliverable. - Diagrams tab excluded from PDF: the Mermaid SVGs in the diagrams tab are built for interactive pan/zoom and paginate very badly in print (mostly blank pages). This is by design -- the SVGs are fully available in the zip and interactive HTML viewer.
- Chromium path changed: the script auto-detects via
find /opt/pw-browsers -name "chrome" | grep -v headless. If auto-detect fails, updateCHROMIUM_DEFAULTin the script. - Loopback connections blocked: do NOT use an HTTP server for PDF rendering -- Playwright's Chromium sandbox blocks
ERR_SOCKET_NOT_CONNECTEDon localhost. Always use the file:// + inline-data approach inscreenshot_report.py. - index.html as file://: will silently fail to load data --
fetch()is blocked onfile://origins in most browsers. Must be served over HTTP. - SVG naming mismatch:
generate_diagrams.pychecks for bothdiagram_<key>-1.svg(mmdc) anddiagram_<key>.svg-1.svg(Docker wrapper) and writes whichever exists intodiagrams.json. If neither exists yet (diagrams not yet rendered), it defaults to the mmdc name -- re-rungenerate_diagrams.pyafter rendering if needed. - Blank 1-page PDF: caused by
inspector.htmlloading mermaid via<script src="vendor/js/mermaid.min.js">, which cannot resolve as a relative path underfile://. This aborts app init beforefetch()fires. Fixed inscreenshot_report.pyby replacing the<script src=...>tag with a lightweight stub:window.mermaid = {initialize(){}, run(){}, contentLoaded(){}}. The diagrams tab is excluded from the PDF so mermaid doesn't need to work -- it just must not throw. Do NOT inline the fullmermaid.min.jsas a<script>block: at ~3 MB of minified JS with no newlines, Chromium's PDF renderer treats it as visible body text, producing pages of garbage output. _in_sandbox()returning False on Firecracker VMs: the function checksIS_SANDBOXenv var first, then/.dockerenvand/run/.containerenv. Firecracker VMs setIS_SANDBOX=yesbut have neither marker file. If_in_sandbox()returns False incorrectly, the script falls through to_docker_available()which crashes ifdockeris not on PATH.dockernot on PATH crash:_docker_available()guards withshutil.which("docker")before invoking it. If docker is absent it returns False cleanly rather than raisingFileNotFoundError.