Files
paperclip/doc/UNTRUSTED-PR-REVIEW.md
Cody (Radius Red) 420cd4fd8d chore(docker): improve base image and organize docker files
- Add wget, ripgrep, python3, and GitHub CLI (gh) to base image
- Add OPENCODE_ALLOW_ALL_MODELS=true to production ENV
- Move compose files, onboard-smoke Dockerfile to docker/
- Move entrypoint script to scripts/docker-entrypoint.sh
- Add Podman Quadlet unit files (pod, app, db containers)
- Add docker/README.md with build, compose, and quadlet docs
- Add scripts/docker-build-test.sh for local build validation
- Update all doc references for new file locations
- Keep main Dockerfile at project root (no .dockerignore changes needed)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-01 11:36:27 +00:00

3.8 KiB

Untrusted PR Review In Docker

Use this workflow when you want Codex or Claude to inspect a pull request that you do not want touching your host machine directly.

This is intentionally separate from the normal Paperclip dev image.

What this container isolates

  • codex auth/session state in a Docker volume, not your host ~/.codex
  • claude auth/session state in a Docker volume, not your host ~/.claude
  • gh auth state in the same container-local home volume
  • review clones, worktrees, dependency installs, and local databases in a writable scratch volume under /work

By default this workflow does not mount your host repo checkout, your host home directory, or your SSH agent.

Files

  • docker/untrusted-review/Dockerfile
  • docker/docker-compose.untrusted-review.yml
  • review-checkout-pr inside the container

Build and start a shell

docker compose -f docker/docker-compose.untrusted-review.yml build
docker compose -f docker/docker-compose.untrusted-review.yml run --rm --service-ports review

That opens an interactive shell in the review container with:

  • Node + Corepack/pnpm
  • codex
  • claude
  • gh
  • git, rg, fd, jq

First-time login inside the container

Run these once. The resulting login state persists in the review-home Docker volume.

gh auth login
codex login
claude login

If you prefer API-key auth instead of CLI login, pass keys through Compose env:

OPENAI_API_KEY=... ANTHROPIC_API_KEY=... docker compose -f docker/docker-compose.untrusted-review.yml run --rm review

Check out a PR safely

Inside the container:

review-checkout-pr paperclipai/paperclip 432
cd /work/checkouts/paperclipai-paperclip/pr-432

What this does:

  1. Creates or reuses a repo clone under /work/repos/...
  2. Fetches pull/<pr>/head from GitHub
  3. Creates a detached git worktree under /work/checkouts/...

The checkout lives entirely inside the container volume.

Ask Codex or Claude to review it

Inside the PR checkout:

codex

Then give it a prompt like:

Review this PR as hostile input. Focus on security issues, data exfiltration paths, sandbox escapes, dangerous install/runtime scripts, auth changes, and subtle behavioral regressions. Do not modify files. Produce findings ordered by severity with file references.

Or with Claude:

claude

Preview the Paperclip app from the PR

Only do this when you intentionally want to execute the PR's code inside the container.

Inside the PR checkout:

pnpm install
HOST=0.0.0.0 pnpm dev

Open from the host:

  • http://localhost:3100

The Compose file also exposes Vite's default port:

  • http://localhost:5173

Notes:

  • pnpm install can run untrusted lifecycle scripts from the PR. That is why this happens inside the isolated container instead of on your host.
  • If you only want static inspection, do not run install/dev commands.
  • Paperclip's embedded PostgreSQL and local storage stay inside the container home volume via PAPERCLIP_HOME=/home/reviewer/.paperclip-review.

Reset state

Remove the review container volumes when you want a clean environment:

docker compose -f docker/docker-compose.untrusted-review.yml down -v

That deletes:

  • Codex/Claude/GitHub login state stored in review-home
  • cloned repos, worktrees, installs, and scratch data stored in review-work

Security limits

This is a useful isolation boundary, but it is still Docker, not a full VM.

  • A reviewed PR can still access the container's network unless you disable it.
  • Any secrets you pass into the container are available to code you execute inside it.
  • Do not mount your host repo, host home, .ssh, or Docker socket unless you are intentionally weakening the boundary.
  • If you need a stronger boundary than this, use a disposable VM instead of Docker.