greydgl--pentestgpt
7e88c03d97
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>
43 行
1.7 KiB
Bash
可执行文件
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
|