스웜 감사
인벤토리화 → 섹션으로 분할 → 각 섹션에 하나의 워크트리와 하나의 감사 에이전트 할당 → 각 에이전트가 검증된 결과를 오케스트레이터에 보고 → 모든 결과에 대한 체인 감사 → 하나의 통합 보고서. 오케스트레이터는 사용자가 시작한 워크트리입니다. 진행하기 전에 각 아티팩트를 사용자에게 보여주고, 범위와 그룹화를 결정하도록 합니다.
0. 사전 점검
다른 작업을 수행하기 전에 세 가지 사항을 결정하세요. 각 미해결 항목을 한 번의 AskUserQuestion 호출로 질문하고(질문 도구가 없으면 일반 텍스트로), 사용자가 답변할 때까지 중단하세요.
위협 모델. 벤더 디렉토리와 설치된 의존성 디렉토리를 제외하고 **/THREAT_MODEL.md를 찾습니다. 템플릿 <…> 플레이스홀더가 없는 파일이 있다면 사용합니다. 그렇지 않으면 사용자에게 물어보되, 사용자가 이미 빠른 실행을 요청한 경우는 예외입니다:
- 위협 모델을 먼저 구축 (권장): 모든 섹션 감사자와 비평가가 해당 컨트롤과 범위 외 목록을 사용하여 전체 스웜의 거짓 긍정을 줄이고 비즈니스 로직 버그를 표면화합니다. 초기에 몇 라운드의 질문이 필요하지만, 이후 감사에서 재사용할 수 있습니다.
- 위협 모델 없이 빠른 실행: 질문도 위협 모델도 없습니다. 섹션 감사자는 인벤토리와 코드만을 기반으로 작업합니다. 스웜이 무엇을 찾는지 확인하는 가장 빠른 방법이지만, 더 많은 노이즈가 예상됩니다.
구축을 선택하면, 이 플러그인에 번들된 security-audit 스킬을 오케스트레이터에서 Skill 도구를 통해 실행하여 위협 모델만 요청하고, 1단계 전에 THREAT_MODEL.md가 생성될 때까지 기다립니다.
분할 전략. 인수에 --by-group [N] 또는 --by-theme이 포함되어 있으면 사용합니다. 그렇지 않으면 질문합니다:
- 주제별 (권장): 섹션은 코드가 수행하는 작업(인증, 계정, 결제, 주문, 관리자, 각 타사 통합별 하나)을 따릅니다. 각 감사자는 전체 흐름을 보므로 여러 진입점에 걸친 버그를 발견합니다. 크기는 다양합니다.
- 그룹별: 약 N개의 진입점(기본값 25)으로 고정 크기 그룹을 소스 순서대로 만듭니다. 감사자당 균일한 작업 부하, 판단 호출 없음, 하지만 하나의 흐름이 두 섹션에 걸쳐 절단될 수 있습니다. 체인 감사(6단계)가 일부를 복구합니다.
범위. 사용자가 지정하지 않은 경우, 어떤 서비스, 디렉토리 또는 종류의 진입점을 다룰지, 그리고 무엇을 제외할지 질문합니다.
1. 진입점 인벤토리화
진입점은 외부 입력이 코드에 도달하는 모든 곳입니다: HTTP 라우트, GraphQL/RPC 핸들러, 웹훅, 큐 및 이벤트 컨슈머, 외부 데이터를 읽는 예약 작업, CLI 명령, 파일 또는 업로드 프로세서, 클라이언트 측 메시지, 딥 링크 또는 IPC 핸들러.
- 리포지토리 언어의 파서(컴파일러 또는 언어 서버 API, 또는 tree-sitter)를 사용하여 찾습니다. 정규식은 사용하지 마십시오: 등록은 여러 줄과 배열을 포함할 수 있습니다. 스크립트를 스크래치패드에 보관하여 다시 실행할 수 있도록 합니다.
- 진입점당 기록: 종류, 이름 또는 메소드 + 경로, 접근 가능한 사용자(공개, 로그인, 관리자, 내부, 서명된 웹훅), 가드(인증, MFA, 캡차, 속도 제한, 입력 스키마, 서명 확인), 핸들러, 전체 미들웨어, 데코레이터, 필터 또는 인터셉터 체인,
file:line. - 놓치기 쉬운 것:
- 프리픽스 아래에 등록된 중첩 라우터, 컨트롤러 또는 핸들러 그룹, 그리고 전달된 객체에 등록하는 헬퍼 함수
- 헬퍼 내부에 전역적으로 등록된 핸들러: 프리픽스 없음
- 이전 프리픽스 수준 또는 포괄 등록에서 상속된 미들웨어, 필터 또는 가드
- 두 번 등록된 하나의 핸들러 그룹: 한 번만 나열하고, 별칭을 기록
- 환경 전용 진입점(스테이징, 디버그, 기능 플래그): 표시합니다
- 의존성이 등록하는 진입점(인증 서버, 관리자 패널, 헬스 체크, 작업 대시보드): 패키지 소스를 읽고 수동으로 추가합니다
- 누락된 항목 찾기: 클라이언트 코드(웹 앱, 모바일 앱, 프록시, 다른 서비스)에서 보내는 모든 경로 또는 메시지를 grep하고, 최상위 수준에 등록된 모든 것을 나열합니다. 사용자에게 추가할 항목을 질문하고, 제외한 항목과 이유를 설명합니다.
- 인벤토리를 오케스트레이터 워크트리에
entry-points.md(또는 사용자가 지정한 이름)로 작성합니다.
2. 섹션으로 분할
- 주제별: 크기가 아닌 코드가 수행하는 작업별로 그룹화하고, 하나의 섹션에 두 개의 서로 다른 신뢰 경계(공개, 파트너, 내부, 워커)를 절대 혼합하지 마십시오. 감사자 하나가 처리하기에는 너무 큰 주제는 분할합니다.
- 그룹별: 인벤토리를 순서대로 약 N개의 그룹으로 자릅니다. 하나의 파일에 속한 진입점은 그룹을 몇 개만 변경할 때 함께 유지합니다.
- 제안된 분할(이름, 개수, 한 줄 내용, 판단 호출)을 보여주고 인벤토리 파일에 쓰기 전에 승인을 기다립니다.
3. 섹션당 하나의 워크트리
각 섹션의 워크트리를 오케스트레이터의 현재 커밋에서 생성하여 모든 섹션이 사용자가 작업 중인 코드를 감사하도록 합니다. command -v mori가 mori를 찾으면 mori를 사용하고, 그렇지 않으면 일반 git을 사용합니다:
| mori | git | |
|---|---|---|
| 생성 | mori new sec-audit-NN-<name> --from <current branch>; 워크트리 경로를 출력합니다 (~/.mori/worktrees/<repo>/ 아래) — 기록합니다 | git worktree add ../<repo>-sec-audit-NN-<name> -b sec-audit-NN-<name> |
| 의존성 | 리포지토리의 .mori.json post_create 단계에 의해 설치되거나, 그렇지 않으면 직접 설치합니다 | 직접 설치합니다 |
| 제거 | mori list --json에서 dirty 확인 후 mori remove <branch> -f; 브랜치가 남아 있으면 삭제합니다 | git status 확인 후 git worktree remove <dir> 및 git branch -D <branch> |
분리된 HEAD에서는 git을 사용합니다 (git worktree add <dir> -b <branch> HEAD). 워크트리를 백그라운드에서 생성합니다.
- 각 워크트리에 복사:
AUDIT_SCOPE.md(섹션의 테이블, 열 노트, "이 진입점만 감사"), 전체 인벤토리, 위협 모델이 구축되었지만 아직 커밋되지 않은 경우 동일한 경로에 복사본. - 오케스트레이터에 받은 편지함 생성:
<orchestrator>/.security-audit/swarm/<section>/. - 분할을 다시 수행하려면: 위와 같이 이전 워크트리와 해당 브랜치를 제거하고(변경 사항을 확인하지 않고 강제 제거하지 마십시오), 다시 생성합니다.
4. 섹션 감사를 병렬로 실행
스크래치패드에 하나의 브리프를 작성하고 섹션당 하나의 백그라운드 에이전트를 해당 브리프를 가리키며 생성합니다. 브리프는 다음을 명시해야 합니다:
- WORKTREE에서만 작업하고, 에이전트 명령(
CLAUDE.md,AGENTS.md)을 읽습니다. WORKTREE 외부에 쓰는 유일한 것은 INBOX(오케스트레이터에 있는 섹션 받은 편지함의 절대 경로)입니다. - 이 플러그인에 번들된
security-audit스킬(또는 사용자가 지정한 다른 스킬)을 Skill 도구를 통해 사용하고,@AUDIT_SCOPE.md로 범위를 지정합니다. 빠른 실행 시에는 빠른 실행임을 알려 질문하지 않도록 합니다. 스킬이 없으면: 각 입력을file:line으로 진입점에서 싱크까지 추적하고, 모든 컨트롤을 지나 도달 가능함을 증명하며, 도달 불가능한 것은 삭제합니다. - 위협 모델이 있는 경우: 추적하기 전에 전체를 읽고, 진입점, 컨트롤 및 범위 외 목록을 사용하며, 절대 덮어쓰지 않습니다. 빠른 실행: 위협 모델 없음, 생성하지 않음. 절대 질문하지 않습니다.
- 모든 후보는 거짓 긍정을 가정하는 새로운 비평가 하위 에이전트로 보내집니다. 생성할 수 없으면 자체 비평하고 결과마다 그렇게 명시합니다.
- Critical/High: 실제 진입점을 통한 실패하는 테스트, 리포지토리의 테스트 러너로 실행, 트리에 남깁니다.
- 비평가가 반환하는 즉시 각 결과를 INBOX에 보고하고, 결과당 하나의 파일 (
NN-<slug>.md)로, 에이전트의 출력이 잘려도 손실되지 않도록 합니다. 형식은 아래와 같습니다. - 차단된 후보도 보고: 싱크에 도달하지만 섹션이 제공할 수 없는 것(id, 토큰, 피해자 작업, 유출된 값, 경쟁 조건)이 필요한 흐름.
status: blocked를 사용하고 정확히 무엇이 누락되었는지 명명합니다. 다른 섹션이 제공할 수 있습니다. - 또한 섹션 보고서를
WORKTREE/.security-audit/<section>-<date>.md에 작성합니다. - 엄격한 규칙: 리포지토리의 안전 규칙을 따릅니다. 마이그레이션이나 데이터베이스 스크립트 없음, git 쓰기 없음, 외부 서비스 호출 없음.
- 최종 메시지: 평결 라인, 결과당 한 라인, INBOX로 보낸 파일 수, 확인되지 않은 항목, 감사 스킬이 호출된 방법.
결과 파일 형식:
---
id: <section>-NN
status: validated | blocked
severity: critical | high | medium | low | info
critic: independent | self
entry_point: <method + path or handler name>
needs: <공격자가 사전에 가져야 하는 것: 계정 유형, id, 토큰, 피해자 클릭, 타이밍>
gives: <공격자가 이후에 가지는 것: 유출된 값, 쓰기 액세스, 세션, 돈, 코드 실행>
test: <path or none>
---
한 줄 주장.
Trace: source `file:line` → … → sink `file:line`.
Repro: 코드 블록의 정확한 입력 (요청, 메시지, 파일).
Controls checked: 확인한 컨트롤과 이것이 이 결과를 막지 못하는 이유.
needs와 gives는 체인 감사가 연결하는 기준입니다. 구체적으로 작성하십시오 ("일부 데이터"가 아닌 "피해자의 주문 id").
하나의 섹션을 직접 인라인으로 감사할 수 있습니다. 동시 하위 에이전트 제한으로 인해 일부 비평가가 차단될 수 있습니다.
5. 체인 전 재확인
모든 섹션 에이전트가 완료되면 받은 편지함을 읽고 파일 수를 각 에이전트의 최종 메시지와 비교합니다. 그런 다음 다음 항목에 대해 직접 새로운 비평가를 실행합니다:
critic: self인 High 또는 Critical 결과- 임시, 조건부 또는 "<다른 서비스>에 의존"으로 표시된 결과: 해당 서비스의 코드(가능한 경우)를 읽고 문제를 해결합니다. 두 서비스 간의 경계에 있는 버그는 각 섹션이 단독으로 놓치는 것입니다.
비평가의 심각도로 결과 파일을 업데이트하고 원본을 was: 라인에 유지합니다.
6. 체인 감사
오케스트레이터에서 전체 받은 편지함에 대해 마지막 감사를 수행하며, 인벤토리와 위협 모델(있는 경우)을 곁에 둡니다. 인라인으로 실행하거나 전체 받은 편지함이 포함된 브리프를 가진 하나의 에이전트로 실행합니다.
- 중복 제거. 동일한 근본 원인(동일한 싱크 및 동일한 누락 컨트롤)을 가진 결과를 하나로 병합하고, 이를 공격하는 모든 섹션과 진입점을 나열합니다. 하나의 버그에 대한 두 개의 진입점은 두 개의 결과가 아니라 더 넓은 폭발 반경을 가진 하나의 결과입니다.
- 연결. 모든 쌍에 대해 한 결과의
gives가 다른 결과의needs를 충족하는지 확인하고,blocked후보도 포함합니다. 또한 일반적인 에스컬레이션을 찾습니다:- 정보 유출 (id, 이메일, 토큰, 내부 URL) → 필요한 IDOR, 계정 탈취 또는 SSRF
- 사용자 열거 + 누락된 속도 제한 → 자격 증명 스터핑 또는 OTP 무차별 대입
- 자체 XSS 또는 HTML 인젝션 + CSRF 또는 로그인 CSRF → 피해자에 대한 저장 XSS
- 오픈 리다이렉트 + OAuth 또는 매직 링크 흐름 → 토큰 도용
- 대량 할당 또는 약한 검증 + 권한 있는 다운스트림 컨슈머 (워커, 관리자 보기, 웹훅)
- 경쟁 조건 + 잔액, 쿠폰, 한도 또는 일회성 작업 → 반복 이득
- 함께 돈을 이동시키거나 한도를 우회하는 두 개의 낮은 영향 비즈니스 로직 간격
- 각 체인을 증명. 모든 링크에서
file:line으로 종단 간 추적하고 각 단계에서 정확한 입력을 사용합니다. 코드에 없는 링크는 체인이 아닙니다. 발명하지 말고, 어떤 결과나 공개 작업도 제공하지 않는 선행 조건이 필요한 링크는 계산하지 마십시오. - 각 체인을 비평 새로운 하위 에이전트와 함께 병렬로 수행합니다. 비평가는 단계가 실제로 연결되지 않는다고 가정하고(다른 사용자, 다른 세션, 만료된 토큰, 순서 지정, 한 단계가 이미 다른 컨트롤에 의해 수정됨) 체인의 심각도를 반환합니다: 최종 이득의 영향 × 모든 단계가 함께 발생할 가능성, 또는 "cleared".
- 테스트 각 Critical 또는 High 체인을 오케스트레이터 워크트리에서 실제 진입점을 통해 모든 단계를 구동하는 하나의 실패 테스트로 테스트합니다.
- 각 체인을
<orchestrator>/.security-audit/swarm/chains/NN-<slug>.md에 결과 형식으로 작성하고,links:에 결과 id를 나열합니다. 구성 결과도 유지합니다.
7. 통합 보고서
오케스트레이터에 .security-audit/<scope>-combined-<date>.md를 작성합니다:
- 중복 제거 후 개수가 포함된 평결 라인, 체인은 별도로 계산("3 chains, 2 raise severity"). 빠른 실행의 경우
security-audit스킬의references/REPORT_FORMAT.md에서 빠른 실행 라인으로 시작합니다. - 체인 우선: 번호가 매겨진 목록의 단계와 입력 및
file:line, 최종 이득, 체인 전후 심각도, 비평가, 테스트 경로. 각 체인을 끊는 단일 수정 사항을 명시합니다. - Critical/High 설명: 정확한 입력이 포함된 재현 단계,
file:line이 포함된 추적, 이득 및 전제 조건, 수정, 비평가, 테스트 경로 및 테스트가 입증하지 못하는 것. - Medium 테이블, Low 목록 (접힘), 차단 해제되지 않은 차단 후보 (접힘: 리드일 뿐 결과가 아님).
- 섹션 간 패턴.
- 적용 범위 격차 및 확인되지 않은 항목 (중단된 에이전트, 받은 편지함 개수 불일치, 프로덕션 구성, 타사 동작, 자체 검토된 비평가).
- 각 워크트리의 보고서 경로가 포함된 섹션 테이블.
아무것도 커밋되지 않습니다. 채팅 요약을 체인 및 Critical/High 테이블로 이끌고, 가장 먼저 배송할 수정 사항을 명시하십시오: 가장 많은 체인을 끊는 것을 선호합니다.