From 1037eab0ccf6e4314fec31b9557481a7c176c2c0 Mon Sep 17 00:00:00 2001 From: kdairatchi <96064915+kdairatchi@users.noreply.github.com> Date: Sat, 18 Apr 2026 07:02:43 -0400 Subject: [PATCH 1/2] docs: reconcile compose paths, document WSL credsStore gotcha Two compose files were confusing users: the root docker-compose.yaml (pulls the published GHCR image, for consumers) and cybersandbox/ docker-compose.yml (builds locally with personal Obsidian/nuclei mounts, for maintainers). The README pointed at the second one via `cd cybersandbox`, dropping new users onto a dev compose with host paths that don't exist on their machines. - Rename cybersandbox/docker-compose.yml -> docker-compose.dev.yml so the filename self-documents its audience. - Point root README at ./docker-compose.yaml (no `cd cybersandbox`). - Document the WSL Docker Desktop credsStore failure mode since it bites anyone pulling the public image from WSL without Desktop running. - Update SETUP.md commands to `-f docker-compose.dev.yml`. --- README.md | 10 ++++++---- cybersandbox/SETUP.md | 16 +++++++++------- ...docker-compose.yml => docker-compose.dev.yml} | 0 3 files changed, 15 insertions(+), 11 deletions(-) rename cybersandbox/{docker-compose.yml => docker-compose.dev.yml} (100%) diff --git a/README.md b/README.md index cf7c464..2d1d52a 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,16 @@ CyberBox pairs a hardened sandbox container with **Prowlr** (a Caido proxy plugi ## Quick start -**Container:** +**Container** (pulls the published image from GHCR): ```bash docker pull ghcr.io/prowlrbot/cybersandbox:latest -cd cybersandbox && docker compose up -d -# Seed wordlists volume (one-time): -./scripts/seed-wordlists.sh +docker compose up -d # uses ./docker-compose.yaml in the repo root ``` +If `docker compose` fails with `docker-credential-desktop.exe not found` on WSL, drop the stale credsStore: `sed -i 's/"credsStore": "desktop.exe",\?//' ~/.docker/config.json` (public images need no auth). + +Building from source (contributors, custom mounts, Obsidian vault) uses `cybersandbox/docker-compose.dev.yml` — see [`cybersandbox/SETUP.md`](cybersandbox/SETUP.md). + **Caido plugins:** - [`prowlr-v0.2.1.zip`](https://github.com/ProwlrBot/CyberBox/releases/latest) (this repo) — scope, AI analysis, Obsidian export, guardrails - [ShadowShell](https://github.com/hahwul/ShadowShell) (hahwul, recommended companion) — multi-tab terminal with split panes, AI-CLI presets (Claude/Gemini/Codex), and `Cmd+J` drop-down overlay. Prowlr's terminal tab is intentionally minimal; ShadowShell covers the serious terminal workflow. diff --git a/cybersandbox/SETUP.md b/cybersandbox/SETUP.md index 26ced3b..9a9b180 100644 --- a/cybersandbox/SETUP.md +++ b/cybersandbox/SETUP.md @@ -1,7 +1,9 @@ -# CyberSandbox Setup +# CyberSandbox Setup (build from source) Docker-based cybersecurity workspace with 160+ tools, dual AI (Ollama + Claude), Caido proxy, Metasploit, and a plugin marketplace. +> This guide builds the image locally from `cybersandbox/Dockerfile` and mounts a personal Obsidian vault + nuclei templates. If you just want to run the published image, use the root `docker-compose.yaml` instead — see the top-level [`README.md`](../README.md#quick-start). + ## Prerequisites - Docker + Docker Compose @@ -23,10 +25,10 @@ cp .env.example .env # Edit .env — at minimum set GIT_NAME and GIT_EMAIL # 2. Build (first build takes 15-20 min) -docker compose build +docker compose -f docker-compose.dev.yml build # 3. Run -docker compose up -d +docker compose -f docker-compose.dev.yml up -d # 4. Access # Browser UI: http://localhost:8082 @@ -158,9 +160,9 @@ docker run --rm -v cybersandbox-exports:/data -v /your/vault:/vault alpine \ ## Rebuilding ```bash -docker compose build --no-cache # Full rebuild -docker compose up -d --build # Rebuild + restart -docker compose down -v # Wipe all data (workspace + exports) +docker compose -f docker-compose.dev.yml build --no-cache # Full rebuild +docker compose -f docker-compose.dev.yml up -d --build # Rebuild + restart +docker compose -f docker-compose.dev.yml down -v # Wipe all data (workspace + exports) ``` ## Troubleshooting @@ -171,4 +173,4 @@ docker compose down -v # Wipe all data (workspace + exports) **Ollama not connecting:** Make sure Ollama is running on the host and accessible at the configured `OLLAMA_HOST`. The default uses Docker's `host.docker.internal`. -**Out of memory:** The container is limited to 8GB by default. Increase `mem_limit` in docker-compose.yml if running heavy scans + Metasploit simultaneously. +**Out of memory:** The container is limited to 8GB by default. Increase `mem_limit` in `docker-compose.dev.yml` if running heavy scans + Metasploit simultaneously. diff --git a/cybersandbox/docker-compose.yml b/cybersandbox/docker-compose.dev.yml similarity index 100% rename from cybersandbox/docker-compose.yml rename to cybersandbox/docker-compose.dev.yml From 4c2bb98e8e76d2cc397992d7a1cf26a957e71a7b Mon Sep 17 00:00:00 2001 From: kdairatchi <96064915+kdairatchi@users.noreply.github.com> Date: Sat, 18 Apr 2026 07:36:15 -0400 Subject: [PATCH 2/2] fix(compose): unblock `docker compose up -d` with published image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verified end-to-end: `Sandbox(base_url="http://localhost:8080") .shell.exec_command(...)` now returns a real response envelope against the pulled image. Two defects in cybersandbox:latest were crashing the container in a restart loop (exit 1/4) before any service bound to :8080: 1. Dockerfile:150 ends with `USER 1000`, but upstream /opt/gem/run.sh expects root entry so it can useradd, chown /opt/jupyter, and write /etc/sudoers.d/$USER. It self-drops to $USER via `su -` before exec'ing supervisord, so running as root at entry doesn't weaken the app-layer posture — hunter still owns every supervised process. Override with user: "0:0". 2. Upstream run.sh defaults USER=gem, USER_UID/GID=1000. The image already baked hunter at UID/GID 1000 (Dockerfile:143), so groupadd --gid 1000 gem blew up with `GID already exists`. Set USER=hunter explicitly in compose env. Both are runtime-only patches; the clean fix is to drop `USER 1000` from the Dockerfile and rebuild the image (see follow-up issue). --- docker-compose.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docker-compose.yaml b/docker-compose.yaml index 85b530a..df2df5d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -2,6 +2,12 @@ services: sandbox: container_name: cybersandbox image: ghcr.io/prowlrbot/cybersandbox:latest + # Upstream /opt/gem/run.sh expects root entry so it can useradd + + # chown /opt/jupyter, then self-drops to $USER via `su -` before + # exec'ing supervisord. The image's Dockerfile prematurely sets + # USER 1000, which breaks that contract. Override to root here; + # the actual services still run as hunter at the app layer. + user: "0:0" security_opt: - seccomp:unconfined extra_hosts: @@ -13,6 +19,12 @@ services: ports: - "${HOST_PORT:-8080}:8080" environment: + # Align runtime user with the image's build-time user (UID/GID 1000). + # Upstream /opt/gem/run.sh defaults to USER=gem, which collides with + # the hunter user baked into cybersandbox and crashes the container. + USER: hunter + USER_UID: "1000" + USER_GID: "1000" PROXY_SERVER: ${PROXY_SERVER:-} JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY:-} DNS_OVER_HTTPS_TEMPLATES: ${DNS_OVER_HTTPS_TEMPLATES:-"https://cloudflare-dns.com/dns-query{?dns}"}