Skip to content

Latest commit

 

History

History
115 lines (87 loc) · 3.41 KB

File metadata and controls

115 lines (87 loc) · 3.41 KB

Running VulnClaw in Docker

The image bundles the Python CLI, the built React Web UI, and the runtimes (npx + uvx) needed by the default MCP servers (memory, fetch). All mutable state (config, sessions, targets, reports) is kept in a /data volume.

Quick start (docker compose)

cp .env.example .env          # add your VULNCLAW_LLM_API_KEY
docker compose up --build      # builds the image and starts the Web UI

Then open http://127.0.0.1:7788.

State persists in the vulnclaw-data named volume across restarts.

Quick start (plain docker)

# Build
docker build -t vulnclaw:latest .

# Run the Web UI (persisting state in a named volume)
docker run --rm -it \
  -p 127.0.0.1:7788:7788 \
  -e VULNCLAW_LLM_API_KEY=sk-your-key-here \
  -v vulnclaw-data:/data \
  vulnclaw:latest

Running CLI commands instead of the Web UI

The entrypoint is the vulnclaw binary, so you can override the command:

# One-off scan (replace TARGET)
docker run --rm -it \
  -e VULNCLAW_LLM_API_KEY=sk-your-key-here \
  -v vulnclaw-data:/data \
  vulnclaw:latest scan TARGET

# Interactive REPL / TUI
docker run --rm -it \
  -e VULNCLAW_LLM_API_KEY=sk-your-key-here \
  -v vulnclaw-data:/data \
  vulnclaw:latest repl

# Show help / available subcommands
docker run --rm vulnclaw:latest --help

With compose:

docker compose run --rm vulnclaw scan TARGET

Configuration

Configuration is supplied via environment variables (see .env.example) and/or the persisted config.yaml written into the /data volume. Environment variables override the config file at startup.

Scanning a target from inside the container

localhost / 127.0.0.1 inside the container refers to the container itself, not your host or another container — so scanning localhost:PORT will never reach a service running elsewhere. Use a routable address instead:

  • Target on your host (e.g. a pnpm dev / npm run dev server): add a host-gateway alias and target host.docker.internal:

    services:
      vulnclaw:
        extra_hosts:
          - "host.docker.internal:host-gateway"

    Then scan host.docker.internal:3000. Note many dev servers bind to loopback only (127.0.0.1 / [::1]); start them on 0.0.0.0 (e.g. --host 0.0.0.0) or the container still won't reach them.

  • Target in another container: put both on the same Docker network and scan it by container/service name (e.g. targetapp:8080):

    services:
      vulnclaw:
        networks: [default, targetnet]
    networks:
      targetnet:
        external: true
        name: <the-target-project's-network>   # `docker network ls`

Verify reachability before scanning:

docker compose exec vulnclaw \
  python -c "import socket; socket.create_connection(('TARGET', PORT), 3); print('reachable')"

Notes

  • The container binds the Web UI to 0.0.0.0 internally (required for the published port to be reachable); the host-side 127.0.0.1:7788 mapping keeps it private to your machine. Change the mapping to expose it elsewhere — only do so on networks you trust, as the UI has no authentication.
  • The chrome-devtools MCP server is disabled by default; enabling it requires a Chrome/Chromium browser which is not installed in this image to keep it lean.
  • The optional knowledge-base feature (kb, ChromaDB) is not installed by default. Add kb to the pip install extras in the Dockerfile if you need it.