Repository navigation
Lab Setup
Two levels of validation: a reproducible local lab, then HTB/authorized lab targets.
The lab runs from a separate compose file (docker-compose.lab.yml), independent of the main stack (docker-compose.yml).
bash scripts/lab_up.sh
# DVWA: http://127.0.0.1:18080
# Juice Shop: http://127.0.0.1:13000
# WebGoat: http://127.0.0.1:18081
PENTESTAI_LAB_URL=http://127.0.0.1:18080 \
pytest tests/test_docker_lab.py -m docker -q
bash scripts/lab_down.shThe targets for this test are real: HTTP requests are actually sent to local containers. It does not touch the internet.
The two compose files do not share a network, so from inside pentestai-pentestai-1 the lab targets are accessed through the host:
# macOS / Windows
docker compose exec -T pentestai \
python3 __main__.py # in shell: target http://host.docker.internal:18080
# Linux: use the host IP, e.g. 172.17.0.1Before testing the lab, make sure the container environment is healthy:
docker cp scripts/env_test.py pentestai-pentestai-1:/tmp/env_test.py
docker compose exec -T pentestai python3 /tmp/env_test.pyFull deployment + smoke test reference: DEPLOYMENT.md.
Prerequisites: written authorization, active VPN, target within scope.
export PENTESTAI_HTB_TARGET=10.10.10.3
export ANTHROPIC_API_KEY=sk-ant-...
pytest tests/test_htb_live.py -m htb -q
python scripts/run_htb.py 10.10.10.3 \
--objective "enumerate services, find entry point" \
--out artifacts/htb/lame.jsonThe runner writes a JSON artifact: target, objective, steps, findings, services. Keep artifacts as evaluation evidence. Do not commit sensitive target data.
Suggested box order:
| Box | Focus | Needs MSF |
|---|---|---|
| Jerry | Tomcat manager WAR upload | No |
| Lame | Samba 3.0.20 / vsftpd 2.3.4 | Yes |
| Forest | AD enumeration / Kerberoast | Yes |
- One run = one target, one objective, one commit hash.
- Record: success/fail, number of steps, time, valid findings, false positives, token cost.
- Do not claim to "outperform" without reproducible run artifacts.
- VCR cassettes for LLM are in
tests/cassettes/; re-record only with your own key:
VCR_RECORD_MODE=all pytest tests/test_llm_vcr.py -m network -qSecrets are filtered by tests/conftest.py.