CLI
Claude Code에 MCP로 꽂아 쓰는 펜테스트 오케스트레이터. 17개 에이전트가 정찰부터 보고서까지 직접 돌리고, 60개 큐레이션 프로브 + 200개 외부 보안 툴 래퍼로 OWASP 주스샵 같은 SPA에서 63% 챌린지 솔브율을 기록한다.
한 줄로 보면.
pentest-ai는 "AI 에이전트한테 펜테스트(침투 시험)를 통째로 맡기는" 오픈소스 도구다. PyPI에서 pip install ptai 한 줄이면 끝이고, 실행 명령도 ptai start https://target.example.com 한 줄이면 된다. 그러면 도구가 알아서 포트 스캔 → 로그인 → 웹 취약점 탐색 → 액티브 디렉토리(AD) 점령 → 클라우드 권한 상승 → 공격 체인 조합 → 검증 PoC 실행 → 마크다운/HTML/PDF 보고서 작성까지 끝낸다.
특이한 점은 LLM을 두뇌로 쓰지만 탐지 자체는 "사람이 만든 결정론적 프로브"가 한다는 설계다. 즉 LLM이 시키지 않아도 같은 60개 프로브가 똑같이 돌아가고, LLM은 결과를 보고 다음에 뭘 칠지 고민하는 코디네이터 역할만 맡는다. 그래서 API 키 없이 Claude Code의 구독만으로도 쓸 수 있다.
트렌드시프트 12위에 오른 이유.
외부 보안 컨설팅은 한 번에 수천만 원 + 2주 일정. AppSec 팀은 ZAP·Burp·Nuclei 같은 도구를 직접 돌려야 하는데 도구마다 인터페이스가 다르고 결과가 노이즈투성이다. pentest-ai는 "200개 보안 도구를 LLM이 알아서 골라 쓰고, 결과를 한 보고서로 합쳐 주는" 인공지능 컨설턴트 한 명을 노트북에 띄우는 것에 가깝다.
경쟁 도구 대비 차별점은 명확하다.
대부분의 자동 스캐너(ZAP, Nuclei)는 로그인 페이지에서 멈춘다. 인증 세션을 유지하지 못해서 그렇다. pentest-ai는 auth_profile 로 로그인 시퀀스를 정의하면 JWT(JSON Web Token)를 뽑아 모든 후속 프로브에 자동 첨부한다. 그래서 "회원 영역의 SQL 인젝션"처럼 인증 뒤에만 보이는 버그를 잡는다.
일반 스캐너는 "여기 취약점일 수도?" 후보 40개를 던지고 사람이 골라야 한다. pentest-ai는 poc_validator 에이전트가 발견된 모든 취약점에 비파괴(non-destructive) 증명 코드(Proof of Concept)를 실제로 돌려 본다. 통과한 것만 보고서에 올라가니 거짓 양성률(False Positive)이 0%에 가깝다.
Path 1 (MCP) 로 설치하면 LLM 비용은 이미 결제 중인 Claude Pro/Max 구독으로 처리되고, pentest-ai는 도구만 제공한다. 즉 OpenAI도, Anthropic API도 따로 안 사도 된다. CI/CD처럼 자동화가 필요하면 Path 3 (Standalone) 로 별도 API 키를 쓰면 된다.
OWASP 주스샵에서 ptai 88개 finding(46개 critical+high), ZAP 593개(critical+high 0개·FP 47%), Nuclei 1개. 번호도 raw 결과도 git에 들어가 있어서 직접 재현할 수 있다. "98.7% 탐지" 같은 검증 불가능한 마케팅 문구를 피한다.
recon(정찰)/web/api_security/ad/cloud/mobile/browser/credential_tester/privesc/vuln_scanner/exploit_chain/poc_validator/detection/report/llm_redteam/social_engineer/wireless 17 종 전문 에이전트가 각자 분야를 맡고, 그 아래로 200개 외부 도구(nmap, sqlmap, hydra, hashcat, BloodHound 등) 래퍼와 60개 사내 큐레이션 프로브가 매달려 있다.
패키지 매니페스트(pyproject.toml)에서 직접 뜯어본 의존성.
pentest-ai는 Python 3.10+ 단일 언어 패키지로, 코어 의존성은 의도적으로 가볍게 유지하고 무거운 기능들은 optional-dependencies 그룹으로 분리해 둔다. 사용자가 필요한 surface만 골라 깔 수 있도록.
@mcp.tool() 데코레이터 하나로 함수를 LLM 노출 도구로 등록.ptai start, ptai mcp 등 50+ 서브커맨드).AWS/Azure/GCP 권한 점검을 할 때만 필요. 세 거대 클라우드의 IAM·미설정·K8s RBAC·서버리스 권한 상승 등을 다룸. pip install ptai[cloud].
LiteLLM 어댑터를 통해 OpenRouter·Azure·DeepSeek·Groq·Mistral·Together AI·Bedrock·Vertex AI·Cohere 등 어떤 LLM API든 같은 인터페이스로 호출. 핵심 설치를 가볍게 유지하려고 옵션으로 분리.
MCP 대신 HTTP REST로 통합하고 싶을 때. ptai serve --port 8888 으로 띄우면 /engagements, /findings, WebSocket 실시간 이벤트 스트림이 열린다.
BrowserAgent가 헤드리스 크롬으로 DOM·XHR·보안 헤더를 직접 분석할 때. 단순 HTTP만으로는 SPA(Single Page Application)의 동적 라우트·XHR 호출이 안 잡혀서 별도 분리.
Cloudflare Turnstile, 브라우저 핑거프린팅 같은 안티봇 우회가 필요한 정찰용. scrapling install --force 로 별도 브라우저 바이너리 추가 다운로드.
관측가능성(observability)을 켤 때. Phoenix, Jaeger, Tempo, Datadog, Honeycomb 등 OTLP 받는 어떤 백엔드로도 trace 송신. LLM 호출 + 도구 실행이 trace span으로 자동 기록.
pentest-ai 자체에 포함되지 않은 200+ 외부 CLI들. ptai setup --tier core 로 6 개 핵심만, --tier recommended 로 30 개, --tier full 로 전부 설치. 엔터프라이즈처럼 "모든 도구를 시스템에 깔지 못하게" 막혀 있어도 해당 도구를 호출하는 경로만 자동으로 건너뛰는 우아한 폴백이 있다.
390 줄짜리 오케스트레이터가 어떻게 17 에이전트를 굴리는가.
전체 흐름을 ASCII로 그리면 이렇다. 화살표는 데이터 흐름이고, 각 박스는 별도 모듈이다.
┌──────────────────────────────────────────────────────────────┐
│ Claude Code / Cursor / Codex (MCP client, LLM 두뇌 역할) │
└────────────────────────────┬─────────────────────────────────┘
│ JSON-RPC over stdio
▼
┌──────────────────────────────────────────────────────────────┐
│ mcp_server/server.py FastMCP @mcp.tool() × 49 도구 │
│ start_engagement / list_tools / run_tool / run_probe / ... │
└────────────────────────────┬─────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ engine/orchestrator.py AgentOrchestrator │
│ ───────────────────────────────────────────────────────── │
│ PHASE_ORDER = [recon, web, ad, cloud, mobile, chaining, │
│ validation, detection, report] │
│ │
│ for phase in PHASE_ORDER: │
│ agent.run(scope, rate_limiter, auth, llm) │
└────────────────────────────┬─────────────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│ recon │ │ web │ │ ad │
│ agent │ │ agent │ │ agent │
└────┬────┘ └────┬─────┘ └────┬─────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────┐
│ tools/registry.py ToolRegistry (200+ wrap) │
│ + SecurityTool 데이터클래스 — command·parser │
│ + BLOCKED_ARG_KEYS — 인자 화이트리스트 │
│ + intensity-aware cache │
└────────────────────────┬────────────────────────┘
│ subprocess.run / asyncio
▼
┌──────────────────┐
│ 외부 보안 도구 │
│ nmap, sqlmap, │
│ hydra, impacket │
└────────┬─────────┘
▼
┌──────────────────────────────────────────┐
│ engine/findings_db.py (aiosqlite) │
│ scope-guarded · deduplicated · evidence │
└────────────────────┬─────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│ chain │ │ poc_val. │ │ detection│
│ agent │ │ agent │ │ agent │
└────┬────┘ └────┬─────┘ └────┬─────┘
└──────────────┼───────────────┘
▼
┌───────────────┐
│ report agent │ md/html/pdf/SARIF/JUnit
└───────────────┘
engine/orchestrator.py 의 PHASE_ORDER 리스트는 9 단계가 무조건 이 순서로 실행된다. 한 단계가 끝나야 다음 단계가 들어가고, 단계마다 findings DB에 결과가 쌓인다. "recon이 끝나야 web이 의미가 있고, web이 끝나야 chain이 의미가 있다"는 펜테스트 방법론이 코드 구조로 그대로 박혀 있다.
건물 침입 시뮬레이션과 같다. 먼저 외부에서 빙 둘러보며 창문·문 위치 파악(recon) → 자물쇠 열어 보고(web/ad) → 들어가서 금고 위치 파악(privesc) → 금고 따기(poc_validator) → CCTV가 무엇을 잡았어야 했는지 보고(detection) → 최종 보고서 작성(report). 순서가 거꾸로면 의미가 없다.
READme의 다섯 강조점 중 가장 중요한 설계 결정. LLM이 없어도 같은 60 개 프로브가 똑같이 돌아간다. LLM은 "이 finding으로 다음에 어디를 칠까" 같은 추론만 담당하고, 실제 탐지 로직은 사람이 큐레이션한 결정론적 파이썬 함수다.
최근 연구(ARTEMIS, DARPA AICC Atlantis, xOffense)에 따르면 완전 자율 LLM 펜테스트 에이전트는 챌린지의 21~31%만 끝낸다. 사람이 중간 개입하는 휴먼-인-더-루프(HITL) 셋업은 64%까지 올라간다. "LLM이 알아서 다 해줄 거야"라는 가정으로 만든 도구는 실전에서 안 잡히는 게 많다.
pentest-ai는 의도적으로 LLM을 "지휘"에만 쓴다. SQL 인젝션·XSS·XXE·JWT alg:none 같은 60 개 패턴은 파이썬으로 결정론적으로 짜여 있고, LLM은 그것들이 만든 finding을 보고 다음 phase를 결정한다. 결과적으로 같은 타깃에서 같은 결과가 나오게(reproducible) 만들었다.
오펜시브 도구의 가장 위험한 실패 모드는 "허락받지 않은 시스템을 공격해 버리는 것". pentest-ai는 engine/scope.py 의 ScopeEnforcer 가 모든 도구 호출 직전에 타깃 호스트가 사전에 선언된 범위 안인지 검증한다. strict_scope=true 옵션을 켜면 HTTP 302 리다이렉트도 따라가지 않는다. 공격자가 http://victim.com/redirect?url=http://attacker.com 같은 트릭으로 스캔을 빼돌릴 수 없다.
ScanProfile.from_intensity(intensity) 가 stealth/safe/normal/aggressive 4 단계 강도에 따라 RPS(초당 요청 수)·동시성·재시도 정책을 동적으로 잡아 준다. 운영 중인 서비스를 다운시키지 않으려는 안전장치. HTTP 429 응답을 받으면 Retry-After 헤더를 존중한다(0.15.1 새 기능). 이후 1.0.0 정식 릴리스를 거쳐 2026-08-05 기준 최신 버전은 v1.2.0(신뢰성 릴리스)이다. 외부 도구가 MCP stdio 파이프의 stdin을 물려받아 httpx·naabu·dnsx 가 무한 대기하던 행업과, 웹 도구들이 HTTPS 전용 호스트에 평문 80 포트로 붙어 조용히 0건을 반환하던 스킴 오판이 이 릴리스에서 수정됐다.
tools/registry.py 의 BLOCKED_ARG_KEYS 집합은 LLM이 도구에 절대 못 넣게 막아야 하는 위험한 인자들이다.
BLOCKED_ARG_KEYS = frozenset({
"script", "script-args", "output", "oN", "oX", "oG", "oA",
"exec", "eval", "command", "cmd", "shell", "system",
"upload", "download", "write", "config",
})
LLM 이 nmap --script vulners {target} 처럼 임의의 NSE 스크립트를 실행하려 하면 차단된다. 키 이름 검증(^[a-zA-Z0-9_-]+$) 과 값 검증(;|&\`$ 등 셸 메타문자 거부)까지 더해서 LLM 프롬프트 인젝션이 셸 인젝션으로 번지는 경로를 막는다.
엔게이지먼트 진행 중 Ctrl+C 를 600 밀리초 안에 두 번 누르면 오케스트레이터가 멈추고 REPL로 떨어진다. step(다음 한 phase만), inspect findings, inject <instruction>(LLM에 추가 지시), skip, resume, abort. 사람이 중간에 개입할 수 있게 명시적으로 설계되어 있다.
35,000 줄짜리 코드베이스를 조감하면.
pentest-ai/
├── cli/ # ptai CLI 진입점 (Typer)
│ ├── main.py # 42개 서브커맨드 (3,154 줄)
│ ├── auth.py # 인증 프로필 관리
│ ├── menu.py # 비-LLM 사용자용 numeric 메뉴
│ ├── install_wizard.py # 200 개 외부 도구 설치 마법사
│ └── mcp_setup.py # 다른 MCP 클라이언트 자동 설정
│
├── mcp_server/ # FastMCP 서버 (LLM 노출 surface)
│ ├── server.py # @mcp.tool() 전체 모듈 합산 약 57개 (1,821 줄)
│ ├── auth.py
│ └── security_tools.py
│
├── api/ # FastAPI HTTP 대안
│ ├── server.py
│ └── static/ # 로컬 웹 대시보드
│
├── engine/ # 핵심 비즈니스 로직
│ ├── orchestrator.py # 9-phase 코디네이터 (390 줄)
│ ├── agent_loop.py # LLM 에이전트 루프 (456 줄)
│ ├── findings_db.py # SQLite + evidence storage
│ ├── scope.py # ScopeEnforcer
│ ├── auth_handler.py # JWT/cookie/Basic auth 핸들링
│ ├── rate_limiter.py # ScanProfile (stealth..aggressive)
│ ├── playbook.py # YAML 플레이북 실행기
│ ├── hitl.py # Ctrl+C 두 번 REPL
│ ├── cvss.py # CVSS v3.1 점수 계산
│ ├── sarif.py # SARIF 2.1.0 출력
│ ├── junit_xml.py # JUnit XML 출력
│ ├── tracing.py # OpenTelemetry 통합
│ ├── llm/ # LLM 클라이언트 (LiteLLM, Anthropic, OpenAI, Ollama)
│ └── probes/ # 60 개 큐레이션 프로브 (SPA-aware)
│
├── agents/ # 17 개 전문 에이전트
│ ├── base.py # BaseAgent 추상 클래스
│ ├── recon/ # 정찰
│ ├── web/ # 웹 + spa_probes.py
│ ├── api_security/ # OpenAPI/GraphQL OWASP API Top 10
│ ├── ad/ # Active Directory
│ ├── cloud/ # AWS/Azure/GCP
│ ├── mobile/, wireless/, browser/
│ ├── credential_tester/
│ ├── privesc/ # 권한 상승
│ ├── vuln_scanner/
│ ├── exploit_chain/ # 멀티-스텝 공격 체인
│ ├── poc_validator/ # 비파괴 PoC 실행
│ ├── detection/ # Sigma/SPL/KQL 룰 생성
│ ├── llm_redteam/ # OWASP LLM Top 10
│ ├── social_engineer/ # phishing corpus
│ ├── report/ # 최종 보고서 (Jinja2 템플릿)
│ └── selection/ # 에이전트 라우팅
│
├── tools/ # 200+ 도구 래퍼
│ ├── registry.py # ToolRegistry (1,578 줄)
│ ├── network/ # nmap, masscan, ...
│ ├── web/ # sqlmap, ffuf, ...
│ ├── osint/, cloud/, binary/, password/
│ ├── wordlists/ # 번들 폴백 단어사전
│ └── plugin_loader.py # 외부 MCP 서버 합치기
│
├── playbooks/builtin/ # 3 개 기본 플레이북 (.yaml)
│ ├── external-recon.yaml
│ ├── web-app-quick.yaml
│ ├── llm-app-redteam.yaml
│ └── ...
│
├── config/ # 기본 설정 (pentest-ai.yaml)
├── benchmarks/ # 재현 가능 벤치마크 하니스
│ ├── challenges/ # 합법 타깃 정의 (Juice Shop 등)
│ ├── scripts/run_all.sh
│ └── results/2026-05-12/juice-shop/ # raw 출력 보관
│
├── docs/ # 사용자 문서
│ ├── benchmarks/juice-shop.md
│ ├── ci-cd.md
│ ├── credentialed-scans.md
│ └── ROADMAP.md
│
├── tests/ # 1,000+ pytest (Python 3.10–3.13)
│ └── honeypot/ # 자체 honeypot 회귀 테스트 (10/10 강제)
│
├── pyproject.toml # 의존성 + 도구 설정
├── Dockerfile # multi-stage (prod / dev)
├── docker-compose.yml
├── AGENTS.md # AI 코딩 에이전트용 기여 가이드
├── SECURITY.md # 취약점 공개 정책
├── DISCLAIMER.md # AUP 동의 텍스트
└── CHANGELOG.md # 42KB, 릴리즈별 상세 기록
두 가지 주목 포인트.
agents/ 는 "무엇을 할지 결정하는 사람", tools/ 는 "그 사람이 손에 쥐는 무기". 같은 nmap도 recon-agent가 호출하면 정찰용 인자가, ad-agent가 호출하면 SMB 포트 집중용 인자가 들어간다. 도구 자체는 1 개만 등록되어 있고 에이전트가 컨텍스트에 맞게 빌드한다.
"juice-shop 점수만 자랑하지 않겠다"는 의지. 자체 작성한 honeypot 앱에 자체 작성한 버그 10 개를 심어 두고 CI에서 "10/10 잡혀야 PR 머지 가능"으로 강제한다. juice-shop은 너무 유명해서 LLM·프로브 모두 학습돼 있는데, honeypot 점수는 큐레이션된 프로브 라이브러리의 실제 커버리지를 노이즈 없이 측정한다.
이 레포에서 한 가지씩 떼어 가져갈 것.
mcp_server/server.py 의 @mcp.tool() 데코레이터 한 줄이면 보통 함수가 LLM이 호출할 수 있는 도구가 된다. 인자는 Pydantic으로 자동 검증된다. 배울 것: MCP 서버를 처음 만들 때 이 패턴이 가장 직관적이다. 인자 타입 힌트가 그대로 JSON-RPC 스키마가 된다.
cli/main.py 는 2,788 줄짜리 단일 파일에 ptai start, ptai mcp, ptai setup, ptai playbook, ptai resume, ptai auth, ptai serve, ptai menu 등 50+ 명령을 담아낸다. 배울 것: Typer가 click 기반으로 어떻게 깊은 하위 명령 트리를 만드는지, B008 ("function call as default")이 왜 Typer에서는 컨벤션인지.
SQLite + 비동기 = 가벼우면서 단일 사용자 환경에 충분. 하지만 워커 스레드가 이벤트 루프보다 오래 사는 미묘한 문제(테스트에서 PytestUnhandledThreadExceptionWarning)가 README의 pytest 설정에서 직접 언급된다. 배울 것: 비동기 SQLite 쓸 때 흔히 마주치는 함정과 그 우회법.
Kerberoasting, AS-REP roasting, DCSync, NTLM relay 같은 Windows AD 공격 기법이 모두 impacket 라이브러리에 들어 있다. agents/ad/ad_agent.py 에서 호출 패턴을 볼 수 있다. 배울 것: 보안 학습 관점에서, AD가 무엇이고 왜 이 공격들이 가능한지 코드를 읽으며 익힐 수 있다.
리액트·뷰처럼 자바스크립트로 렌더하는 SPA는 단순 HTTP GET만으로는 라우트·XHR 호출이 안 보인다. BrowserAgent가 헤드리스 크롬으로 진짜 페이지를 띄워 DOM·네트워크·콘솔까지 캡쳐한다. 배울 것: 크롤러 만들 때 언제 HTTP만으로 충분하고 언제 Playwright/Puppeteer가 필요한지.
playbooks/builtin/external-recon.yaml 처럼 phase·depends_on·condition·tools만으로 메서드론을 표현한다. 배울 것: 비슷한 패턴 — GitHub Actions workflow, Ansible playbook, dbt project — 모두 같은 디자인이다. 도메인 전문가가 코드 안 건드리고 워크플로를 정의하게 만드는 표준 패턴.
engine/tracing.py 가 LLM 호출 + 도구 실행을 trace span으로 자동 기록. Phoenix 같은 LLM 관측 도구에 OTLP로 보내면 어떤 프롬프트가 어떤 도구를 부르고 토큰을 얼마나 썼는지 시각화된다. 배울 것: AI 에이전트를 디버깅하려면 trace가 필수. 처음부터 OpenTelemetry 표준으로 가는 게 정답.
SARIF(Static Analysis Results Interchange Format)는 보안 도구가 결과를 GitHub Code Scanning으로 보낼 때 쓰는 표준 JSON. engine/sarif.py 가 findings DB 의 데이터를 그대로 SARIF로 변환한다. 배울 것: 보안 도구 만들 때 사람이 읽을 보고서 + 기계가 읽을 SARIF 두 출력을 모두 내는 게 업계 표준.
특정 LLM 벤더에 묶이지 않으려면 LiteLLM 어댑터 한 겹. OpenRouter, Bedrock, Vertex AI, Ollama 같은 다양한 백엔드를 같은 인터페이스로 호출. 배울 것: 자신의 AI 프로젝트에 LLM 호출 한 줄을 추가할 때 처음부터 LiteLLM으로 시작하면 나중에 모델 갈아탈 때 코드 안 바꾼다.
실제로 돌리려면 뭐가 필요한가.
다행히 가볍다. 코어 자체는 Python만 있으면 되고, 무거운 건 외부 보안 도구 쪽이다.
masscan 등 raw socket 쓰는 도구는 root/sudo 필요. 대부분 도구는 일반 사용자로 충분.ANTHROPIC_API_KEY, OPENAI_API_KEY, 또는 로컬 Ollama 중 하나.PTAI_PRICE_LIMIT=25 같은 env로 조정.난이도별 5 개. 합법 타깃에서만 시도할 것.
pentest-ai는 실제 공격 행위를 수행한다. 외부 시스템을 허락 없이 스캔하면 한국 정보통신망법, 미국 CFAA(Computer Fraud and Abuse Act), EU GDPR 32 조 등에 의해 형사 처벌 대상이다. 실습용으로는 자기 노트북에 띄운 OWASP Juice Shop, DVWA, HackTheBox, TryHackMe 같은 허락된 환경만 쓸 것.
Juice Shop은 일부러 취약하게 만든 학습용 웹 앱. docker run -d -p 3000:3000 bkimminich/juice-shop 으로 띄우고 ptai start http://localhost:3000. 17 개 critical, 7 개 attack chain이 나오는지, 보고서가 어떻게 생겼는지 직접 확인. CHANGELOG의 최신 v1.2.0 항목과 본인 결과를 비교.
claude mcp add pentest-ai -- ptai mcp 한 줄로 등록. Claude Code를 재시작하고 "내 로컬 Juice Shop 인스턴스(http://localhost:3000)에 대해 인증된 펜테스트 돌려 줘. 결과를 마크다운 보고서로 정리해 줘"라고 자연어로 시켜 본다. LLM이 어떤 MCP 도구를 어떤 순서로 부르는지 관찰.
playbooks/builtin/web-app-quick.yaml 를 카피해서 my-api-pentest.yaml 로 변경. phases 에 surface-check(헤더 점검) → api-discovery(OpenAPI 스펙 찾기) → auth-probe(JWT 무효 알고리즘 시도) → rate-limit-test 4 단계를 정의하고 ptai playbook run ./my-api-pentest.yaml. 본인 REST API(자기 소유)에 돌려 본다.
아직 wrap 되지 않은 보안 도구(예: katana, httpx-toolkit)를 골라서 tools/registry.py 에 SecurityTool 인스턴스 추가. build_args(인자 빌더) 와 parse_output(결과 파서) 만 짜면 된다. tests/test_tool_X.py 에 단위 테스트 추가하고 PR 보내기. AGENTS.md의 "Definition of done" 체크리스트를 모두 통과해야 함.
본인 사이드 프로젝트에 staging 환경을 띄우고, .github/workflows/security.yml 에 README 예시처럼 ptai 를 워크플로로 추가. --fail-on high 로 게이팅하고 SARIF 출력을 GitHub Code Scanning에 업로드. Pull Request 코멘트로 finding이 자동으로 달리는 걸 확인. 난도가 높은 이유 — staging 환경 + 인증 자격 증명 + 비밀 관리(GitHub Secrets)까지 손봐야 한다.
8 주 코스로 보면.
SQL Injection, XSS, CSRF, SSRF, XXE, Broken Auth, Sensitive Data Exposure, Misconfig, Outdated Components, Insufficient Logging. Juice Shop 가이드북(OWASP 공식, 무료)을 따라 하나씩 직접 익스플로잇해 본다. 이론만 보지 말고 손으로 명령어를 친다.
모든 웹 공격은 HTTP 한 줄 한 줄에서 일어난다. Burp Suite Community로 본인 트래픽을 가로채 보고 헤더·바디·쿠키·세션 토큰의 흐름을 눈으로 본다. 그 다음 sqlmap, ffuf, nuclei 같은 명령형 도구로 같은 일을 자동화해 본다.
pentest-ai의 모든 코드는 비동기 파이썬. async def, await, asyncio.gather, TaskGroup 사용 패턴을 익힌다. Pydantic v2 모델로 LLM JSON 출력을 검증하는 패턴(response_model)도. 이게 익숙해지면 어떤 LLM 도구도 만들 수 있다.
modelcontextprotocol.io의 공식 사양을 읽고 FastMCP로 본인 도메인의 도구를 노출하는 MCP 서버를 만들어 본다. 예: "내 노션 워크스페이스 조회 도구", "내 GitHub 이슈 검색 도구". pentest-ai/mcp_server/server.py를 코드 참고로.
Windows AD가 회사망의 사실상 표준이라 펜테스트는 거의 다 AD로 귀결된다. TryHackMe의 "Attacking Kerberos" 룸 + impacket README의 GetUserSPNs.py, GetNPUsers.py, secretsdump.py 사용법. 가상 머신으로 AD 도메인 컨트롤러를 띄우고 본인 도메인을 공격해 본다.
flaws.cloud와 flaws2.cloud (무료 학습 환경)를 단계별로 풀면서 S3 misconfig, IAM 권한 escalation, Lambda 환경 변수 노출, EC2 Metadata Service 공격을 손으로 익힌다. 그 다음 ptai의 cloud agent + prowler/scout-suite가 같은 패턴을 어떻게 자동화하는지 코드를 본다.
공격뿐 아니라 방어도 익혀야 한다. agents/detection/ 의 룰 생성 로직을 읽고 Sigma 명세서를 본 다음 자신의 EDR/SIEM 데이터(Splunk/Sentinel/Elastic free tier)에 룰을 직접 배포해 본다. "공격하면 어떻게 로그가 남고, 그걸 어떻게 잡는가"의 양면을 모두 봐야 진짜 보안 전문가다.
학습이 진심이면 자격증으로 객관 측정. OSCP(가장 유명, 24시간 실기), PNPT(현실적인 코스, AD 중심), CRTP(AD만 깊게). pentest-ai는 이런 자격증 학습의 보조 도구로 쓰면 좋다 — "이 명령어 왜 이렇게 짜는 거지?"의 답을 코드에서 찾을 수 있어서.
레포 곳곳에 나오는 약자·전문 용어 정리.
engine/cvss.py 가 자동 계산.impacket-GetUserSPNs 명령 한 줄.Ctrl+C 두 번이 pentest-ai의 HITL 진입점.~/.pentest-ai/aup-consent.txt 에 기록. 위반 시 책임은 사용자에게.더 깊이 파고들 때 직접 열어 볼 1차 출처와 핵심 기술 문서.
pip install ptai 의 배포처. 릴리즈별 버전과 의존성 확인.@mcp.tool() 데코레이터로 MCP 서버를 짜는 프레임워크 가이드(학습 포인트 1의 기술).claude mcp add pentest-ai -- ptai mcp 한 줄. 자연어로 "내 로컬 staging 환경 점검해 줘" 시켜 보고 LLM이 어떤 도구를 어떤 순서로 부르는지 관찰. API 키 없이 시작 가능.engine/orchestrator.py + 한 에이전트(예: agents/web/web_agent.py)만 정독. 비동기 + LLM + 외부 도구 호출의 결합 패턴이 모든 AI 에이전트의 공통이다.tools/registry.py 의 BLOCKED_ARG_KEYS + 정규식 인자 검증 패턴을 그대로 가져다 쓴다. 프롬프트 인젝션이 셸 인젝션으로 번지는 흔한 경로를 차단하는 표준 방어법.engine/sarif.py 가 100 줄 안에 변환 로직을 보여 준다.benchmarks/ 처럼 raw 출력 + 스크립트 + 결과 마크다운을 git에 함께 커밋. "98.7% 정확도" 같은 검증 불가 마케팅 대신 "n=1 single-shot, methodology 여기"의 정직한 형식이 신뢰를 만든다.