# MSD Core 보안 모델 > **설명** — 이 문서는 MSD Core가 현재의 보안 자세를 갖는 *이유*와 *계층들이 > 어떻게 맞물리는지*를 설명한다. 모든 훅 파라미터에 대한 레퍼런스가 아니다. > `/msd-secure-phase` 명령과 옵션에 대해서는 [명령어](../COMMANDS.md)를 참조하라. > 구현 수준의 훅 아키텍처에 대해서는 > [아키텍처 § 훅 시스템](../ARCHITECTURE.md#hook-system)을 참조하라. > 조직 전반의 보안 기준선(스캐너 제어, 인시던트 체크리스트, 소유권 모델)에 대해서는 > [SECURITY.md](../../../SECURITY.md)를 참조하라. --- ## AI 기반 개발에 전용 보안 자세가 필요한 이유 일반적인 코드 에디터는 사용자를 대신하여 임의의 패키지를 실행하지 않는다. MSD Core는 그렇게 한다. 리서치 → 계획 → 실행 파이프라인은 "패키지 이름 지정"에서 "`npm install ` 실행"까지, "계획 결과물 작성"에서 "해당 결과물을 LLM 시스템 프롬프트로 사용"까지의 전체 경로를 자동화한다. 각 자동화 단계는 루프에서 사람을 제거한다 — 그리고 각 제거는 잠재적인 공격 표면이다. MSD Core의 보안 모델은 하나의 조직 원칙을 중심으로 구축된다: **심층 방어(defence in depth)**. 어떤 단일 제어도 완벽하다고 가정하지 않는다. 여러 겹치는 계층이 각각 고유한 종류의 위험을 줄이며, 함께 공격 표면을 완전히 제거하지는 않지만 악용하기 상당히 더 어렵게 만든다. 이 문서 끝의 솔직한 요약은 시스템이 방어할 수 없는 것을 설명한다. --- ## 계층 1 — 공급망 보호: 패키지 적법성 게이트 ### 위협 AI 모델은 패키지 이름을 환각한다. 이것은 변두리 실패 모드가 아니다: 2025년 연구에서 AI가 생성한 패키지 참조의 약 20%가 합법적인 패키지와 대응되지 않는 환각된 이름으로 문서화되었다. 그 환각된 이름들의 일부 — 같은 연구에서 약 43% — 는 프롬프트 전반에 걸쳐 일관되게 반복되며, 이는 공격자가 AI 도구들이 일반적으로 생성하는 이름을 관찰하고 악의적인 설치 후 스크립트로 npm, PyPI, 또는 crates.io에 해당 이름들을 선점 등록할 수 있다는 것을 의미한다. 이 기법을 *슬롭스쿼팅(slopsquatting)*이라고 한다. 슬롭스쿼팅의 교활한 특성은 `npm view`를 통과하는 환각된 이름이 *합법적으로 보인다*는 것이다. 레지스트리 항목은 누군가가 이름을 등록했다는 것만 증명한다 — AI가 말한 것을 패키지가 한다거나, 합법적인 사용자가 있다거나, 설치 스크립트가 안전하다는 것은 증명하지 않는다. 게이트 없이는 환각된 이름이 MSD의 리서처 → 플래너 → 실행기 파이프라인을 통해 감지되지 않고 흐르다가 결국 사용자의 기계에서 `npm install `로 실행될 것이다. ### 게이트 작동 방식 게이트는 세 가지 파이프라인 단계에 걸쳐 작동한다: **리서치 단계.** `msd-phase-researcher`가 외부 패키지를 추천할 때 각 패키지에 대해 `msd-tools query package-legitimacy check --ecosystem `을 실행한다. 결과는 `RESEARCH.md`의 `## Package Legitimacy Audit` 테이블에 작성된다. `[SLOP]`로 태그된 패키지들(높은 신뢰도의 환각 또는 공격자가 등록)은 파일이 저장되기 전에 **`RESEARCH.md`에서 완전히 제거된다**. 이런 패키지들은 절대 플래너에게 도달하지 않는다. **계획 단계.** `msd-planner`는 감사 테이블을 읽는다. `[SUS]`(의심스러움: 최근 등록, 낮은 다운로드 수, 소스 저장소 없음, 또는 인기 있는 패키지와 가까운 명명 패턴)나 `[ASSUMED]`(직접 레지스트리 검증이 아닌 WebSearch에서 출처)로 태그된 모든 패키지에 대해, 플래너는 설치 단계 전에 **`checkpoint:human-verify` 작업을 삽입한다**. 체크포인트에는 레지스트리 페이지로의 직접 링크와 살펴봐야 할 구체적인 항목들이 포함된다: 유지관리자 이력, 이슈 트래커 활동, 의심스러운 설치 스크립트의 부재. **실행 단계.** 설치가 실패하면 `msd-executor`는 **체크포인트를 표시하고 중지한다**. 대체 패키지 이름을 조용히 시도하지 않는다 — 그 자체가 악의적일 수 있다. 이는 실행기 동작의 명시적인 규칙이다(실행기 에이전트 정의의 RULE 3). ### WebSearch 패키지가 항상 `[ASSUMED]`인 이유 WebSearch를 통해 발견된 패키지 이름은 `npm view`가 성공하는지 여부에 관계없이 `[ASSUMED]`로 태그된다. 레지스트리에 존재하는 패키지가 설치하기에 안전한 패키지와 같지 않다. `npm view`는 등록을 증명하지, 적법성을 증명하지 않는다. `[ASSUMED]` 태그는 `[SUS]`와 동일한 사람 검증 체크포인트를 트리거하여, 검증되지 않은 웹 검색 추천이 설치 전에 항상 사람의 검토를 받도록 보장한다. ### 생태계 커버리지 리서처는 단일 일반 검사 대신 레지스트리별 검증 명령을 사용한다: - Node.js: `npm view` - Python: `pip index versions` - Rust: `cargo search` 이는 2025년 USENIX 연구에 따르면 약 9% 발생률의 교차 생태계 환각을 커버한다 — AI가 실제로 사용 중인 것이 아닌 한 생태계에서는 존재하지만 다른 생태계에서는 없는 패키지를 추천하는 경우. ### 정상적인 성능 저하 `slopcheck`을 사용할 수 없는 경우(설치되지 않았거나 리서치 시점에 pip 설치 실패), MSD는 가장 엄격한 폴백을 적용한다: **모든 추천 패키지가 `[ASSUMED]`로 태그되고**, 플래너는 모든 설치에 `checkpoint:human-verify` 작업을 게이트로 건다. 리서치와 계획 수립은 정상적으로 진행된다 — 시스템은 누락된 도구 의존성으로 인해 하드 실패하지 않는다. 이것은 의도적으로 정상 흐름보다 더 엄격하다: slopcheck 사용 불가는 모든 패키지 설치에 사람 체크포인트를 받는다는 것을 의미한다. `slopcheck` 도구는 MIT 라이선스이며 pip으로 설치 가능하다. 유지 관리가 중단되더라도 `[ASSUMED]`-게이트 폴백은 사람 체크포인트 커버리지가 유지되도록 보장한다. --- ## 계층 2 — 프롬프트 인젝션 방어 ### 위협 MSD Core는 LLM 시스템 프롬프트가 되는 마크다운 파일을 생성한다. 리서치 파이프라인은 외부 웹 콘텐츠를 읽는다; 계획 파이프라인은 사용자가 제공한 텍스트(`--text-file`, `--prd`)를 통합한다; 실행 파이프라인은 에이전트 컨텍스트로 나중에 다시 읽히는 계획 결과물을 작성한다. 이런 결과물들에 흐르는 사용자가 제어하는 텍스트는 잠재적인 **간접 프롬프트 인젝션** 벡터이다 — 시스템 프롬프트 안에 들어가면 에이전트의 지시 사항을 재정의하거나 정보를 유출하려는 공격자가 제어하는 문자열. ### 방어 작동 방식 MSD Core는 세 가지 수준에서 프롬프트 인젝션을 다룬다. **입력 유효성 검사(`security.cjs`).** `msd-core/bin/lib/security.cjs` 모듈은 중앙 보안 유틸리티이다. 다음을 제공한다: - 경로 탐색 방지: 사용자가 제공한 파일 경로(`--text-file`, `--prd`)가 프로젝트 디렉터리 내에서 해결되도록 유효성이 검사되며, macOS의 `/var` → `/private/var` 심링크 해결이 명시적으로 처리된다 - 프롬프트 인젝션 탐지: 알려진 인젝션 패턴(역할 재정의, 지시 우회, 시스템 태그 인젝션)이 사용자가 제공한 텍스트에서 계획 결과물에 들어가기 전에 스캔된다 - 안전한 JSON 파싱: 제작된 JSON 페이로드를 통한 프로토타입 오염 공격을 방지하는 래퍼 - 쉘 인수 유효성 검사: 하위 쉘 명령에 전달되는 인수가 사용 전에 유효성이 검사된다 **런타임 훅: `msd-prompt-guard.js`.** 이 훅은 `.planning/` 파일을 대상으로 하는 모든 Write 또는 Edit 호출에서 실행된다. 작성되는 콘텐츠를 `security.cjs`와 동일한 인젝션 패턴으로 스캔한다(독립성을 위해 훅에 직접 인라인된 하위 집합 — 훅은 모듈 경로가 변경되더라도 실행되도록 모듈을 `require()`하지 않는다). 탐지는 **자문적 전용**이다: 훅은 결과를 로그하지만 쓰기를 차단하지 않는다. 이유는 합법적인 계획 쓰기에 대한 오탐지 차단이 이차 스캔 계층에서 놓친 인젝션보다 더 방해가 될 것이기 때문이다. **런타임 훅: `msd-read-injection-scanner.js`.** 이 훅은 모든 Read 도구 호출의 출력에서 실행된다. 방금 읽은 *콘텐츠*를 신뢰할 수 없는 콘텐츠의 주입된 지시 사항으로 스캔한다 — 공격자가 MSD가 에이전트 컨텍스트에 통합하려는 파일에 지시 사항을 내장한 경우를 잡아낸다. **CI 스캐너.** `prompt-injection-scan.security.test.cjs`는 테스트 스위트의 일부로 내장된 인젝션 벡터가 있는지 모든 에이전트, 워크플로우, 명령 파일을 스캔한다. 이는 MSD 소스 자체의 인젝션 시도를 잡아낸다 — 예를 들어 워크플로우 파일을 수정하여 역할 재정의 지시 사항을 추가하는 공급망 공격. ### 읽기 인젝션 스캐너 vs 프롬프트 가드 두 훅은 보완적인 표면을 커버한다. `msd-prompt-guard.js`는 *계획 결과물에 대한 쓰기*를 감시한다 — 심어지는 인젝션을 잡는다. `msd-read-injection-scanner.js`는 *모든 파일의 읽기*를 감시한다 — 외부 콘텐츠(의존성의 README, 타사 설정 파일, 사용자가 제공한 문서)에서 수집되는 인젝션을 잡는다. 함께 수집 → 저장 → 재독 수명 주기를 괄호로 묶는다. --- ## 계층 3 — 저장소 및 의존성 무결성 MSD의 런타임 동작 상류에서 `open-gsd` 조직은 저장소와 패키지 수준에서 제어를 시행한다. 이것들은 [`docs/security/baseline.md`](../../security/baseline.md)에 완전히 문서화되어 있으며 완전성을 위해 여기에 요약된다. **의존성 무결성.** 모든 타사 의존성은 `package-lock.json`을 통해 고정되고 설치 전에 공개된 체크섬에 대해 검증된다. `scripts/check-npm-integrity.cjs` 게이트는 CI 시점에 유효하지 않은 버전, 누락된 패키지, 불필요한 패키지를 탐지한다. 이는 MSD 자체 의존성에 대한 의존성 혼동 및 오타스쿼팅 공격을 완화한다. **비밀 스캔.** 모든 커밋과 PR은 하드코딩된 비밀이 있는지 스캔된다. 의도적인 테스트 픽스처는 프로젝트 표준 제외 문법으로 주석을 달아야 한다(주석 형식은 `SECURITY.md` 참조). 주석이 없는 억제는 CI를 실패시킨다. **로케일 안전 텍스트 스캔.** 출력 및 사용자 대면 문자열은 유니코드 동형 문자, 양방향 오버라이드 문자, 보이지 않는 유니코드에 대해 스캔된다 — 차이점에서 악의적인 콘텐츠를 숨길 수 있는 CVE-2021-42574("Trojan Source")에 문서화된 공격 클래스. --- ## 트레이드오프와 한계 여기에 설명된 보안 모델은 AI 기반 개발을 위한 공격 표면을 의미 있게 줄인다. 공급망 위험을 제거하지는 않는다. **패키지 적법성 게이트가 줄이는 것:** 환각되거나 공격자가 등록한 패키지가 사람 체크포인트 없이 `npm install`에 도달할 확률. `[SLOP]` 게이트는 높은 신뢰도의 나쁜 패키지를 완전히 제거한다; `[SUS]` / `[ASSUMED]` 게이트는 실행 전에 사람 검토를 요구한다. 이는 성공적인 슬롭스쿼팅 공격의 비용을 상당히 높인다. **패키지 적법성 게이트가 제거하지 않는 것:** 나중에 손상된 합법적인 패키지(계정 탈취, 자체 트리의 의존성 혼동)는 리서치 시점의 등록 신호를 확인하는 slopcheck에 의해 잡히지 않는다. 잠금 파일과 의존성 무결성 계층의 `npm audit`이 그 공격 클래스에 대한 제어이다. **프롬프트 인젝션 방어가 줄이는 것:** 계획 결과물의 사용자가 제어하는 텍스트가 에이전트 지시 사항을 성공적으로 재정의할 확률. 알려진 인젝션 형태에 대한 패턴 매칭은 일반적인 경우를 잡는다; 새로운 탈옥이나 저신호 인젝션은 탐지되지 않고 통과할 수 있다. 자문 전용 자세는 탐지가 로그되지만 차단되지 않는다는 것을 의미한다 — 탐지 시 하드 정지하지 않는 비용으로 워크플로우 연속성을 보존하는 의도적인 선택. **프롬프트 인젝션 방어가 제거하지 않는 것:** 알려진 패턴과 일치하지 않는 충분히 창의적인 인젝션, 또는 훅이 커버하지 않는 채널을 통해 도달하는 인젝션(예: 서브에이전트가 문서를 탐색하면서 읽는 의존성의 공개된 README에 주입된 콘텐츠). 심층 방어는 각 계층이 공격을 더 어렵게 만들지, 어떤 단일 계층이 불가능하게 만들지 않는다는 것을 의미한다. **취약점 신고.** `https://github.com/open-gsd/gsd-core/security/advisories/new`에서 비공개 GitHub 보안 보고서를 통해 신고하라. 공개 이슈를 열지 말라. 응답 일정과 공개 정책은 [SECURITY.md](../../../SECURITY.md)를 참조하라. --- ## Related - [명령어](../COMMANDS.md) — 보안 관련 플래그가 있는 `/msd-secure-phase`와 `/msd-code-review` 포함 - [아키텍처 § 훅 시스템](../ARCHITECTURE.md#hook-system) — 모든 훅, 이벤트 트리거, 안전 속성에 대한 구현 상세 - [SECURITY.md](../../../SECURITY.md) — 취약점 신고, 조직 전반 보안 기준선, 비밀 스캔 제외 거버넌스, 의존성 무결성 검증 - [문서 인덱스](../README.md)