项目文件夹

文件
gelei 7e88c03d97 feat: dockerized tool with persistent Claude+Codex login + multi-model benchmark
Run the autonomous CTF/pentest tool in Docker with a one-time, persistent login for
BOTH Claude Code and Codex, and add a multi-model benchmark harness.

Backend (multi-model):
- Add `--backend {claude,codex}` to the CTF pipeline. CodexBackend (pentestgpt/core/
  backend.py) wraps unified_agent's Codex backend and translates its events into
  AgentMessages, so the same pipeline runs on Claude (opus/sonnet) or Codex
  (gpt-5.5/gpt-5.4-mini). Wired through config.backend, pipeline stage construction,
  and the CLI (+ PENTESTGPT_CODEX_EFFORT; greppable [CODEX_USAGE] under PENTESTGPT_BENCH=1).

Docker tool (tool-only image; the benchmark stays OUTSIDE the image):
- Extend Dockerfile: Codex CLI (@openai/codex) + openai_codex SDK + unified_agent/
  pentestgpt_agent/pentestgpt_legacy packages + gobuster/dirb + socat. Add .dockerignore
  (keeps creds/benchmark/workspace out of the build context).
- Persistent dual login (the hard part) — asymmetric by token model:
  * Claude: `setup-token` -> token stored in the pentestgpt-claude volume; entrypoint
    exports CLAUDE_CODE_OAUTH_TOKEN (setup-token does not write .credentials.json; macOS
    host creds live in the Keychain and can't be copied).
  * Codex: the container does its OWN `codex login` (NOT seeding -- ChatGPT refresh tokens
    are single-use, so a shared/copied login 401s on first refresh). The 127.0.0.1:1455
    OAuth callback is forwarded into the container via a socat hop (-p 1455:8455).
  * scripts/docker-login.sh is idempotent: checks logins live, logs in only the missing one(s).
- docker-compose codex-config volume (+ pinned names); entrypoint token-export + non-blocking
  preflight; scripts/docker-auth-status.sh; Make targets (docker-build/login/auth-status/
  run/shell/down/nuke).
- Verified end-to-end: one `make docker-login` -> a fresh container reports claude+codex
  logged in with live round-trips; the CTF pipeline (Codex) captured a flag against an
  isolated fixture and the pentest pipeline ran cleanly; persists across recreation, no re-login.

Benchmark (multi-model, host-side):
- benchmark/pilot/ harness (run_pilot.py + report.py): builds each xbow challenge, discovers
  the loopback port, runs the pipeline across the 4 model combos, judges by the baked
  FLAG{sha256(UPPER-dir)}, and renders REPORT.md (infra failures excluded from solve rates).
  Includes the partial pilot's results (results.jsonl + REPORT.md).

Docs: docs/docker-dev-plan.md (full plan + implementation status); CLAUDE.md and README
docker quickstart; benchmark/pilot/README.md; design-doc roadmap (docs/redesign).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 23:58:23 +08:00

43 行
1.7 KiB
Bash
可执行文件

#!/usr/bin/env bash
# Runs INSIDE the container. Reports whether Claude Code and Codex are logged in.
# Exit 0 only if BOTH are authenticated. Lightweight (no token spend) by default;
# pass --roundtrip to additionally do a 1-token live check on each.
set -uo pipefail
roundtrip=false
[ "${1:-}" = "--roundtrip" ] && roundtrip=true
claude_ok=false
codex_ok=false
# Use a persisted Claude OAuth token (from `make docker-login`) if present. This is
# needed when this script runs via `--entrypoint bash` (which bypasses entrypoint.sh).
if [ -s "$HOME/.claude/oauth_token" ] && [ -z "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]; then
export CLAUDE_CODE_OAUTH_TOKEN="$(cat "$HOME/.claude/oauth_token")"
fi
# Claude is authed if it has a persisted OAuth token (setup-token), a subscription
# credentials file, or an API key in the environment.
if [ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ] || [ -s "$HOME/.claude/.credentials.json" ] || [ -n "${ANTHROPIC_API_KEY:-}" ]; then
claude_ok=true
fi
# Codex: file-based session in ~/.codex/auth.json; `codex login status` confirms validity.
if codex login status >/dev/null 2>&1; then
codex_ok=true
elif [ -s "$HOME/.codex/auth.json" ]; then
codex_ok=true
fi
if $roundtrip; then
$claude_ok && { claude -p "reply with exactly OK" --model sonnet 2>/dev/null | grep -qi OK || claude_ok=false; }
$codex_ok && { codex exec -m gpt-5.4-mini -c model_reasoning_effort="low" --skip-git-repo-check \
"reply with exactly OK" 2>/dev/null | grep -qi OK || codex_ok=false; }
fi
printf " claude: %s\n" "$($claude_ok && echo 'logged in' || echo 'NOT logged in')"
printf " codex: %s\n" "$($codex_ok && echo 'logged in' || echo 'NOT logged in')"
$claude_ok && $codex_ok && exit 0
exit 1