AI 코딩 에이전트를 위한 멀티 에이전트 정적 애플리케이션 보안 검토 하네스: 코드베이스를 매핑하고, 취약점 클래스를 추적하며, 발견 사항을 연쇄 검증하고, SARIF, JSON, PDF로 보고합니다.
Claude Code(그리고 추후 다른 AI 에이전트)를 위한 멀티 에이전트 애플리케이션 보안 검토 하네스입니다. 하나의 라우터 스킬이 코드베이스를 매핑하고, 클래스별 지식 베이스로 취약점을 사냥하며, 발견 사항을 연쇄시켜 에스컬레이션으로 연결하고, 실제 영향을 검증한 뒤, README / JSON / SARIF / doc / PDF로 보고하는 완전한 공격 보안 파이프라인으로 디스패치합니다.
범위: 이 하네스는 자신이 소유하거나 테스트 권한이 있는 코드에 대해 정적 분석(소스 검토, 데이터 흐름 추적, PoC/페이로드 구성)을 수행합니다. 실제 제3자 시스템을 공격하지 않습니다.
security-harness/ # a plugin marketplace └── plugins/security-harness/ ├── skills/ │ ├── sh-router # single entry point - routes any appsec request │ ├── sh-security-review # the pipeline orchestrator (Stages 0-5) │ └── sh-kb-* (15) # per-vuln-class knowledge bases ├── agents/ │ ├── sh-recon # map: Graft graph + stack/SBOM/CVE + attack surface │ ├── sh-hunter # find: source→sink hunting, one per class (parallel) │ ├── sh-chainer # escalate: combine findings into attack chains │ ├── sh-verifier # confirm: offensive + seceng + dev verification + PoC │ └── sh-reporter # deliver: README/JSON/SARIF/HTML/PDF/doc └── references/ # shared contracts (finding schema, SARIF map, state files, rubrics)
### 커버되는 취약점 클래스 (`sh-kb-*` 스킬)
access-control (IDOR/BOLA/priv-esc) · sqli · xss · ssrf · injection (cmd/code/SSTI/LDAP) · auth (session/JWT)
· deserialization · path-traversal (LFI/RFI) · secrets · csrf · xxe · open-redirect · crypto · race-conditions
· file-upload. 의존성 CVE/SBOM은 recon 단계에서 처리됩니다.
## 설치
이 하네스는 여러 에이전트용으로 제공됩니다. 전체 패키징 세부 사항과 릴리스
체크리스트는 [`docs/DISTRIBUTION.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/docs/DISTRIBUTION.md)에 있습니다.
**Claude Code** - 이 저장소를 플러그인 마켓플레이스로 추가하고 플러그인을 설치하세요:```
/plugin marketplace add dmdhrumilmistry/security-harness
/plugin install security-harness
/plugin marketplace add는 다음 중 하나를 허용합니다: GitHub owner/repo(위와 같음), 전체 git URL
(https://github.com/dmdhrumilmistry/security-harness.git), 또는 클론의 로컬 경로
(예: 체크아웃이 있는 디렉터리에서 /plugin marketplace add ./security-harness).
그런 다음 /plugin install security-harness를 실행하고, 프롬프트가 표시되면 다시 로드하세요.
Gemini CLI - 네이티브 확장, 저장소 루트에 매니페스트가 있음:```bash gemini extensions install https://github.com/dmdhrumilmistry/security-harness
**opencode, Codex 또는 모든 [agentskills.io](https://agentskills.io) 에이전트** - 스킬을
검색 디렉터리에 복사하세요. Codex는 추가적으로 `AGENTS.md`를 자체적으로 인식합니다:```bash
git clone https://github.com/dmdhrumilmistry/security-harness
cd security-harness
python3 scripts/sync-agent-skills.py --install agents # ~/.agents/skills
python3 scripts/sync-agent-skills.py --install opencode # ~/.config/opencode/skills
Graft는 파이프라인에 의해 자동으로 설치되고 설정됩니다. Stage 0은 Graft가 없으면 npm install -g @nanonets/graft를 실행하고(Node/npm 필요), 그다음 graft init <target> --no-agents --no-global을 실행하여
대상 저장소에 대한 Graft MCP 서버와 freshness 훅을 등록합니다. 그래프 자체(<target>/graft/,
자동 gitignore됨)는 recon 중에 빌드됩니다. 수동으로 미리 설치하려면: npm install -g @nanonets/graft. Graft의
구조적 빌드는 무료이며 API 키가 필요 없습니다. 선택적 --deep LLM 패스는 설정된 경우 GRAFT_API_KEY /
GRAFT_PROVIDER / GRAFT_MODEL을 사용합니다.
다른 도구들도 Stage 0에 의해 없으면 자동 설치됩니다 (머신에 있는 패키지 관리자를 통해 -
winget/choco/scoop, brew, apt, npm/pip/go - references/tooling-setup.md 참조). 설치는 알림이 표시되고,
권한 상승이 필요 없는 방법을 선호하며, 실행을 절대 차단하지 않습니다. 설치할 수 없는 것은 단순히
사용 불가로 표시되고 파이프라인은 폴백합니다. Stage 0은 누락된 기능 그룹을 채우는 것만 설치합니다:
syft · CVE: grype
(선호), trivy, 또는 osv-scanner 중 하나wkhtmltopdf 또는 pandoc (PDF/DOCX용); 그렇지 않으면 report.html(또는 헤드리스 Chrome PDF)을 받습니다.이들 모두는 선택 사항입니다 - 아무것도 설치되지 않으면 파이프라인은 네이티브 검색 + 매니페스트 파싱으로 우아하게 성능이 저하됩니다.
자연어 요청으로 라우터를 호출합니다:``` /sh-router full security review of ./api /sh-router find SQLi and IDOR in src/ /sh-router just map this codebase # recon only
또는 파이프라인을 직접 호출하세요:```
/sh-security-review . classes:sqli,access-control,ssrf depth:deep
/sh-security-review . stage:report # regenerate reports for the latest run
각 단계는 인지 부하에 맞춰진 모델에서 실행되므로, 토큰은 발견 품질이 실제로 좌우되는 곳에 사용되고 기계적인 작업에서는 절약됩니다. 이것이 기본값이며, 인수가 필요하지 않습니다.
| 단계 | 기본 모델 |
|---|---|
| recon | sonnet |
| hunt (클래스별) | 패턴 클래스(secrets, crypto, open-redirect, csrf)에는 haiku · 소스→싱크 추적(sqli, xss, ssrf, injection, path-traversal, xxe, file-upload, auth)에는 sonnet · 심층 로직 클래스(access-control, race-conditions, deserialization)에는 opus |
| chain | opus |
| verify | opus (정밀도 게이트 - 강하게 유지됨) |
| report | haiku |
models: 인수로 재정의할 수 있습니다(라우터를 통해서도 전달됨):```
/sh-security-review . # default tiered map above
/sh-security-review . models:max # every stage + hunter on opus (max quality, max cost)
/sh-security-review . models:cheap # aggressive downshift (trades some verify precision)
/sh-security-review . models:verify=opus,hunt=sonnet # per-stage overrides
/sh-security-review . models:report=sonnet,hunt.pattern=sonnet # per-hunter-tier override
단계: `setup, recon, hunt, chain, verify, report`. 모델: `opus, sonnet, haiku, inherit`. `hunt`의 경우,
모델을 그대로 지정하면 모든 헌터가 해당 모델로 통일되며, `hunt.pattern` / `hunt.trace` / `hunt.logic`은 특정 계층을 대상으로 합니다.
다른 토큰 절약 기능도 내장되어 있습니다. recon은 실제 공격 표면이 있는 클래스에 대해서만 헌터를 생성하고, 헌터는
전체 파일을 읽는 대신 Graft 그래프를 조회하며, `findings.json`/SARIF는 모델이 아닌
결정적 스크립트에 의해 생성됩니다.
### 출력
모든 결과는 `<target>/.security-harness/<run-id>/` 아래에 저장됩니다:
- `recon.md`, `codebase-map.json` - 맵 (스택, SBOM, CVE, 공격 표면).
- `findings.jsonl` → `chains.md` → `verified.jsonl` - 작업 상태 (`references/state-files.md` 참조).
- `reports/` - `README.md`, `findings.json`, `results.sarif`, `report.html`, `report.pdf` (+ `report.docx`).
게시된 각 발견 사항에는 페이로드, PoC, 검증 판정, CWE/OWASP ID, CVSS, 그리고
코드 수준의 완화책이 포함됩니다.
## 풀 리퀘스트 리뷰
`sh-pr-review`는 전체 코드베이스가 아닌 단일 풀 리퀘스트를 리뷰하고, 결과를
**PR 자체에** 인라인 코멘트로 게시하며, 브랜치 보호가 적용할 수 있는
`security/pr-review` 커밋 상태를 설정합니다.
**읽을 수 있는 모든 PR에 대해 자신의 머신에서 실행하세요.** 플러그인을 설치하고 요청하세요:```
review https://github.com/acme/api/pull/128
review PR 42
security review this PR
PR 링크를 붙여넣으면 해당 저장소의 PR을 리뷰하며, 먼저 임시 디렉터리로 클론합니다. 헌터들은 패치뿐 아니라 파일도 읽기 때문입니다. 작업 중인 저장소에는 아무것도 기록되지 않습니다.
숫자만 넘기면 현재 있는 저장소, 즉 git remote가 가리키는 저장소를 기준으로
해석합니다. 아무것도 넘기지 않으면 현재 브랜치의 열린 PR을 가져옵니다.
Phase 7은 발견 사항과 판정을 출력하고 무엇이든 게시하기 전에 물어봅니다 - 거절은 정상적인 결과이며, 페이로드는 나중에 게시할 수 있도록 디스크에 남아 있습니다.
분석에 비용을 쓰기 전에 대상 저장소에 실제로 쓸 수 있는지 확인하므로, 다른 사람의 프로젝트를 리뷰할 때 게시가 403이 될 것임을 10분 뒤에 발견하는 대신 미리 알려줍니다.
노이즈가 아니라 머지 게이트로 쓸 수 있게 하는 세 가지 속성이 있습니다:
introduced, aggravated,
pre_existing 중 하나의 pr_impact를 가집니다. 처음 두 개는 차단하고,
pre_existing은 보고되지만 절대 차단하지 않습니다. 작성자가 쓰지도 않은 코드 때문에
머지를 차단하면 필수 검사가 삭제되므로, 헌터가 aggravated와 pre_existing 사이에서
확신이 없을 때는 pre_existing을 골라야 합니다.sh-kb-* 베이스가 사용하는 것과
동일한 클래스 슬러그에 매핑한 다음 티어를 고릅니다. Tier 0(보안 관련 변경 없음)은
아무것도 실행하지 않고도 상태를 설정합니다. Tier 3은 전체 파이프라인을 실행합니다.| 판정 | 상태 | 조건 |
|---|---|---|
| fail | failure | --fail-on(기본 medium) 이상의 introduced 또는 aggravated 발견 사항, 신뢰도 >= 80 |
| warn | success | introduced 또는 aggravated 없음; pre-existing 발견 사항 보고됨 |
| pass | success | 발견 사항 없음, 또는 트리아지가 Tier 0에서 중단됨 |
| error | error | 리뷰를 완료할 수 없음 |
warn이 의도적으로 success를 보고하는 이유: 머지를 차단하는 경고는 단계만 늘어난
실패이며, 팀은 검사를 제거하는 것으로 대응합니다. error는 failure와 구분되게
유지되어, 망가진 실행이 찾지 못한 취약점처럼 보이는 일이 없습니다.
리뷰 이벤트는 항상 COMMENT이며, REQUEST_CHANGES나 APPROVE가 아닙니다. 커밋
상태가 강제 메커니즘이며, 브랜치 보호가 읽는 것이 바로 이것입니다.
범위: 이 스킬은 풀 리퀘스트와 커밋 상태에만 쓰고, 다른 곳에는 쓰지 않습니다. 이슈를 열지 않고 어떤 외부 트래커에도 아무것도 생성하지 않습니다.
PR은 푸시마다 한 번 리뷰되므로, 두 번째 리뷰는 첫 번째보다 저렴해야 합니다. 그렇지 않으면 이 도구는 사람들이 꺼버리는 것이 됩니다.
중복 제거는 게시 전이 아니라 비용 지출 전에 일어납니다. PR에 이미 있는 지문은 Phase 1에서 읽혀 헌터와 검증자에게 전달됩니다. 끝에서 중복을 찾는다면 파이프라인에서 가장 비싼 모델이 PR에 내내 적혀 있던 결론을 이미 재확인한 뒤일 것입니다. 여기에는 캐시가 필요 없습니다. 상태가 PR에 있으므로 콜드 머신과 CI에서도 작동합니다.
로컬 캐시가 나머지를 증분식으로 만듭니다. sh-review-cache는 각 실행의 파일
해시, 발견 사항, 판정을 OS 캐시 디렉터리에 저장합니다(교차 저장소 리뷰는 삭제되는
임시 클론에서 실행되므로 저장소에는 절대 저장하지 않습니다). 다음 리뷰는 내용이 실제로
변경된 파일만 다시 헌팅하고, 변경되지 않은 발견 사항의 판정을 재사용하며, 커버하는
것이 아무것도 움직이지 않았다면 정찰 맵을 재사용합니다.
베이스 브랜치 머지는 비용이 들지 않습니다. main을 PR 브랜치에 머지하면 헤드
SHA가 바뀌고 작성자가 쓴 것은 아무것도 바뀌지 않지만, 커밋 상태는 SHA에 고정되므로
필수 검사가 새 헤드에서 조용히 사라집니다. PR 자체의 파일이 바이트 단위로 동일하고
동시에 베이스 델타가 발견 사항이 의존하는 어떤 것도 건드리지 않을 때, 이전 판정이
에이전트를 전혀 실행하지 않고 새 SHA에 다시 스탬프됩니다. 마지막 조건이 이것을
안전하게 만듭니다: 새니타이저를 삭제하는 베이스 머지는 모든 PR 파일을 변경하지 않은
채로 두면서 안전한 줄을 익스플로잇 가능한 줄로 바꿉니다.
무효화는 의도적으로 보수적입니다. 보안 도구의 오래된 항목은 도구를 느리게 만드는 게
아니라 틀리게 만들기 때문입니다. 캐시 키는 모든 sh-kb-* 지식 베이스를
해싱하므로, KB 업데이트는 모든 캐시된 발견 사항을 무효화합니다 - 캐시된 "clean"이
그 업데이트가 잡으려고 작성된 발견 사항을 억제해서는 절대 안 됩니다. 모델 정체성,
스킬 버전, 파일 내용, 7일 TTL도 모두 무효화하며, 지정되지 않은 모델은 미스로
취급됩니다.
--no-cache는 이를 비활성화하고, --refresh-cache는 재기준화하며, run.md는 각
단계에서 무엇이 실행되고, 재사용되고, 건너뛰어졌는지 기록하므로, 조용히 적중을
멈춘 캐시가 가정이 아니라 눈에 보이게 됩니다.
리뷰와 커밋 상태는 기본적으로 게시됩니다. 계산되고 전달되지 않은 리뷰는 아무도
돕지 못했습니다. --confirm은 게시 전 프롬프트를 복원하고, --dry-run은 아무것도
보내지 않으며, --no-status는 리뷰를 게시하되 커밋 상태는 그대로 둡니다.
게시는 직접 만든 API 호출이 아니라 scripts/sh-pr-post.py를 통해 이루어집니다.
이는 필수 꼬리 단계가 있는 다단계 작업이기 때문입니다: 리뷰, 그다음 상태, 그다음
영수증, 그리고 422는 줄 번호를 옮기는 대신 코멘트를 이동하여 복구됩니다. 이
스크립트는 상태를 pending으로 남긴 채 종료하지 않습니다 - 리뷰를 게시할 수
없으면 여전히 error를 설정하여, PR을 고발하는 대신 도구가 실패했음을 말합니다.
인라인 코멘트는 신뢰도 >= 80인 medium 이상의 발견 사항에만 사용됩니다. 낮은 심각도의 발견 사항은 접힌 본문 섹션에 들어가므로, 낮은 우선순위의 발견 사항이 인라인 코멘트 0개로 나타나는 것은 실패가 아니라 정책이 작동하는 것입니다.
모든 실행은 비용이 얼마나 들었는지 기록하므로, "캐시가 작동하고 있다"와 "리뷰가 느려졌다"가 의견의 문제가 아니게 됩니다.```bash python3 /scripts/sh-metrics.py path # where records live python3 /scripts/sh-metrics.py report # aggregate, by model python3 /scripts/sh-metrics.py purge --older-than-days 30
두 개의 append-only JSONL 파일 - `runs.jsonl`(repo, PR, tier, verdict, totals, 전달한 플래그)과 `events.jsonl`(각 phase 또는 agent당 한 줄: model, tokens, duration, outcome, 캐시에서 재사용되었는지 여부). JSONL이므로 크래시가 발생한 실행도 크래시 위쪽에 유효한 줄을 남긴다.
| Platform | Metrics | Cache |
|---|---|---|
| **Linux / BSD** | `$XDG_DATA_HOME/security-harness/metrics`<br>기본값 `~/.local/share/security-harness/metrics` | `$XDG_CACHE_HOME/security-harness`<br>기본값 `~/.cache/security-harness` |
| macOS | `~/Library/Application Support/security-harness/metrics` | `~/Library/Caches/security-harness` |
| Windows | `%LOCALAPPDATA%\security-harness\metrics` | `%LOCALAPPDATA%\security-harness\cache` |
Linux는 XDG Base Directory 명세를 따르므로, 둘 다 설정된 경우 `XDG_DATA_HOME`과 `XDG_CACHE_HOME`을 존중하고 설정되지 않은 경우 `~/.local/share`와 `~/.cache`로 폴백한다. `SH_METRICS_DIR`과 `SH_REVIEW_CACHE_DIR`로 둘 중 하나를 직접 재정의할 수 있다.
**`python` vs `python3`에 관하여:** 대부분의 Linux 배포판은 `python3`를 제공하며 `python`은 전혀 없다. 따라서 여기의 예제는 `python3`를 사용한다. 번들된 스크립트는 `#!/usr/bin/env python3` shebang을 가지며 실행 가능하므로, `./scripts/sh-metrics.py report`는 Linux와 macOS에서 직접 작동한다. 스킬은 실행당 한 번 `PY="$(command -v python3 || command -v python)"`를 해석하며, 이는 Windows의 Git Bash를 포함한 세 플랫폼 모두를 커버한다.
**철저히 로컬.** 어느 스크립트에도 네트워크 코드나 리포팅 엔드포인트가 없다. 토큰 형태의 모든 것은 기록되기 전에 리댁션된다. 로컬 파일은 이슈에 붙여넣어지기 때문이다.
### 무인 실행
선택 사항이며, 스킬 사용과는 별개의 결정이다. 먼저 한동안 자신의 PR에서 수동으로 실행하여, 팀 앞에서 말하기 전에 자신의 코드베이스에 대해 무엇을 말하는지 파악하라.
준비가 되면, [`references/pr-review-mapping.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/plugins/security-harness/references/pr-review-mapping.md)의 "Enforcing the check on a repository"에 **당신의** repo를 위한 복사-붙여넣기 워크플로가 있으며, 죽은 작업이 필수 체크를 `pending` 상태로 남기는 것을 막는 fail-safe도 포함되어 있다.
임계값은 기본값인 `medium`으로 유지된다. 기존 발견 사항은 절대 머지를 차단하지 않으므로, 스캔되지 않은 코드베이스가 첫날부터 빨간 벽을 만들어내지 않는다 - PR이 실제로 도입하거나 악화시킨 것만 실패시킬 수 있다.
## 작동 방식
1. **Setup** - 사용 가능한 도구를 탐색하고, 범위를 정의하고, 실행 디렉터리를 생성한다.
2. **Recon** (`sh-recon`) - Graft 그래프를 구축하고, 스택/버전을 감지하고, SBOM + CVE를 수집하고, 진입점, 신뢰 경계, 위험한 싱크를 열거한다.
3. **Hunt** (`sh-hunter` ×N, 병렬) - 관련 클래스당 하나의 hunter가 자신의 `sh-kb-*` 지식 베이스를 로드하고, 공격자 입력을 소스에서 싱크까지 추적하고, 후보를 기록한다. 공유 **attempts ledger**는 에이전트들이 서로의 프로브를 반복하는 것을 막는다.
4. **Chain** (`sh-chainer`) - 발견 사항을 더 높은 심각도의 공격 경로로 구성한다.
5. **Verify** (`sh-verifier`) - 먼저 반박하고, 그다음 증거로부터 익스플로잇 가능성을 확인하고, PoC를 구축하고, CVSS를 할당하고, 오탐을 제거한다.
6. **Report** (`sh-reporter`) - 산출물을 생성한다.
서브에이전트는 파일 외에는 아무것도 공유하지 않는다. 계약은 `plugins/security-harness/references/state-files.md`에 있다.
## 확장
공유 템플릿(When to hunt · Sources & sinks · Detection recipe · Payloads/PoC · False-positive filters · CWE/OWASP · Chaining hints · Mitigation)을 따라 `skills/sh-kb-<class>/SKILL.md`를 생성하여 새로운 취약점 클래스를 추가한 다음, 그 slug를 `references/finding-schema.json`의 `class` enum과 `skills/sh-router/SKILL.md`의 라우팅 테이블에 추가한다.
## 자동화된 지식 베이스 업데이트
예약된 GitHub Action(`.github/workflows/update-knowledge-base.yml`)이 `sh-kb-*` 지식 베이스를 최신 상태로 유지한다. **격일로**(그리고 수동 `workflow_dispatch` 시), 에이전트를 실행하여 새롭고 신뢰할 수 있는 공개 보안 연구 - OWASP, PortSwigger Research, CWE/CAPEC, NIST, MDN, 큐레이션된 GitHub repo, 공개 HackerOne 공개 정보 - 를 작고 출처가 명확한 개선 사항으로 정제한다. 그런 다음 **두 번째, 적대적 리뷰어 에이전트**가 결과 diff에서 악성/주입된 콘텐츠를 스캔하고, PR은 **그 리뷰어가 승인한 경우에만 자동 머지된다**.
### 두 개의 워크플로, 세 개의 작업
PR 생성은 리뷰 및 머지와 의도적으로 분리되어 있어, diff를 작성하는 것이 그것을 배포하기로 결정하는 것이 결코 아니다.
**Stage 1 - [`update-knowledge-base.yml`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/workflows/update-knowledge-base.yml)**
(예약 또는 수동). 하나의 작업, `create-pr`:
1. **Generate** - 에이전트가 허용 목록 소스에서 KB를 편집한다. 커밋도, 푸시도 없다.
2. **Open PR** - 결정적 단계가 `automated/kb-update` 브랜치에 PR을 열고(또는 업데이트하고), `awaiting-review` 라벨을 붙인다.
3. **Hand off** - PR 생성이 성공하면 PR 번호와 함께 stage 2를 디스패치한다.
**Stage 2 - [`kb-review-and-merge.yml`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/workflows/kb-review-and-merge.yml)**
(stage 1에 의해 디스패치되거나, 임의의 자동화 PR에 대해 수동으로 실행). 두 개의 작업:
- **`review`** - *별도의* 에이전트 실행이 diff를 **적대적으로** 검사하여 prompt-injection 흔적, 범위 밖 편집, 시크릿/유출, PII, 무기화된 익스플로잇, 허용 목록 외 소싱, 또는 하우스 스타일 위반을 찾는다. **웹도 셸도 없으며**, **fail closed**한다: 의심스러운 것, 불확실성, 또는 누락된 verdict 파일 → REJECT. verdict는 PR 코멘트로 게시되고 라벨을 결정한다.
- **`merge`** - `APPROVE`에서**만** 실행되며, PR을 머지한다. `REJECT`는 이를 건너뛰고 `blocked` 작업이 이유를 보고한다.
> **`pull_request` 트리거 대신 dispatch를 쓰는 이유:** `GITHUB_TOKEN`으로 열린 PR은 `pull_request` 워크플로를 트리거하지 않는다. `workflow_dispatch`는 그 재귀 가드에서 면제되는 두 이벤트 중 하나이므로, stage 1이 안정적으로 핸드오프할 수 있다.
**자동 머지는 승인하는 에이전트가 `main`에 코드를 배포한다는 뜻이다.** 이에 대한 통제:
- 머지 작업은 닫혔거나, 포크에서 온, 또는 head 브랜치가 `automated/*` 밖에 있는 PR을 거부한다(워크플로의 `ALLOWED_HEAD_PREFIX`).
- GitHub 자체의 auto-merge를 선호하므로 **브랜치 보호가 여전히 적용된다**. `main`에 승인 리뷰를 요구하는 규칙이 있으면, PR은 머지되는 대신 대기열에 들어가 사람을 기다린다. auto-merge가 꺼져 있는 repo에서만 즉시 머지로 폴백한다.
- 수동 실행 시 `auto_merge` 입력을 `false`로 설정하여 머지 없이 리뷰할 수 있다.
- 리뷰어 프롬프트는 에이전트에게 그 verdict가 권고가 아니라 구속력이 있음을 알린다.
> 워크플로가 PR을 열 수 있도록 repo 설정 **"Allow GitHub Actions to create and approve pull requests"**(Settings → Actions → General → Workflow permissions)가 필요하다. auto-merge에도 불구하고 사람을 루프에 두고 싶다면, PR과 최소 하나의 승인 리뷰를 요구하는 브랜치 보호 규칙으로 `main`을 보호하라 - auto-merge 경로가 이를 존중한다.
### 플러그 가능한 에이전트
두 stage 모두 [`.github/actions/ai-agent`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/actions/ai-agent/action.yml)를 통해 실행되며, 이는 구성한 에이전트로 디스패치하는 composite action이다. Claude Code, OpenAI Codex, Gemini CLI, 그리고 그 외 모든 것을 위한 탈출구:
| `agent` | 실행 | 자격 증명 |
|---|---|---|
| `claude` (기본값) | `anthropics/claude-code-action@v1` | `CLAUDE_CODE_OAUTH_TOKEN` 또는 `ANTHROPIC_API_KEY` |
| `codex` | `codex exec --full-auto` | `OPENAI_API_KEY` |
| `gemini` | `gemini --yolo --prompt` | `GEMINI_API_KEY` |
| `custom` | 당신의 `KB_AGENT_INSTALL` / `KB_AGENT_COMMAND` | 필요한 것 |
`workflow_dispatch` 입력에서 실행별로 선택하거나, repo 변수를 설정하여 기본값을 변경한다: 생성기용 `KB_AGENT`와 `KB_MODEL`, 리뷰어용 `KB_REVIEW_AGENT`와 `KB_REVIEW_MODEL`. 생성기와 리뷰어를 **서로 다른 에이전트**에서 실행하는 것은 의미 있는 강화 단계이다: 한 모델에 맞춰진 주입이 두 번째, 독립적인 모델에 적중할 가능성은 낮다.
`agent: custom`의 경우, `KB_AGENT_COMMAND`를 셸 명령으로 설정한다. 프롬프트는 `$AGENT_PROMPT_FILE`로 명명된 파일에 작성되고, `$AGENT_MODEL`이 모델 입력을 전달한다.
생성기가 열린 웹을 읽으므로 prompt-injection 방어:
- **도메인 허용 목록.** `WebFetch`는 `.github/kb-update/trusted-sources.md`의 신뢰할 수 있는 도메인으로 제한된다(워크플로의 `--allowedTools`에 미러링됨). `WebSearch`는 URL을 발견할 수 있지만, 허용 목록에 있는 도메인만 실제로 fetch될 수 있다.
- **콘텐츠는 데이터이지 명령이 아니다.** 작업 프롬프트(`.github/kb-update/prompt.md`)는 Claude에게 fetch된 모든 바이트를 신뢰할 수 없는 참조 자료로 취급하고 페이지에 내장된 모든 지시를 무시하도록 지시한다 - HackerOne 리포트 본문(사용자 생성)은 최고 위험 등급으로 표시된다.
- **생성기에는 셸도, 푸시도 없다; 리뷰어가 게이트다.** 생성기는 파일만 편집할 수 있다. 독립적인 리뷰어(`.github/kb-update/review-prompt.md`)가 fetch된 콘텐츠와 `main` 사이에 서는 것이다 - 명시적 승인 없이는 아무것도 머지되지 않는다.
- **생성기와 리뷰어에 서로 다른 에이전트.** 선택 사항이며, 게이트의 가장 강력한 형태이다: `KB_AGENT`와 `KB_REVIEW_AGENT`를 두 개의 서로 다른 엔진으로 설정하라.
**설정:**
- 사용하는 에이전트의 자격 증명을 추가한다(Settings → Secrets and variables → Actions):
**`CLAUDE_CODE_OAUTH_TOKEN`**(기본값), `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, 또는 `GEMINI_API_KEY`.
OAuth 토큰은 종량제 API 키가 아니라 **당신의 Claude 구독 사용 한도**에 대해 인증한다 - 로컬에서 `claude setup-token`으로 생성하고(활성 Claude Pro/Max 구독 필요) 결과를 붙여넣어라.
- 워크플로가 PR을 열 수 있도록 **"Allow GitHub Actions to create and approve pull requests"**(Settings → Actions → General → Workflow permissions)를 활성화한다. 권장: `main`에 PR과 승인 리뷰를 요구하는 브랜치 보호 규칙을 추가하여, auto-merge가 켜져 있어도 사람 없이는 어떤 자동화 변경도 배포될 수 없게 하라.
- 허용되는 소스를 변경하려면 `trusted-sources.md`의 허용 목록**과** 워크플로의 일치하는 `WebFetch(domain:...)` 항목을 편집하라 - 둘을 동기화 상태로 유지하라.
각 실행은 수행한 작업을 `.github/kb-update/last-run-summary.md`에 기록한다.
## 로드맵
- ~~Codex / Cursor 미러 배선.~~
✅ 출시됨: `AGENTS.md`, Gemini CLI 확장, 그리고 `.agents/skills`와 opencode를 위한 `scripts/sync-agent-skills.py`. [`docs/DISTRIBUTION.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/docs/DISTRIBUTION.md) 참조.
- ~~큐레이션된 참조 위에 지식 베이스의 선택적 라이브 fetch 증강(PortSwigger/OWASP/CWE).~~
✅ 위의 예약된 지식 베이스 업데이터로 출시됨.
- `needs-runtime` 발견 사항의 런타임 확인을 위한 선택적 DAST 브리지.
## 라이선스
MIT