Files
msd-core/docs/ko-KR/explanation/security-model.md
Colin cd5db1f8db test(suites): seed security/slow/integration suites via measured retags
Renames (git mv) with all references updated (ci-test-scope RULES,
windows-parity allowlist, test-file-count allowlist, docs in 6 locales):

- 5 scanner tests -> *.security.test.cjs — the 'Run security tests' CI step
  ran zero files since the suite taxonomy landed; it is now honest.
- graphify-auto-update -> *.slow.test.cjs (36s, slowest file in the suite;
  e2e gsd-tools spawns) — runs on full-matrix lanes and push to next.
- installer-migration-install-integration -> *.integration.test.cjs
  (13s; an integration test by its own name).

Coverage gate measured after retags: 88.55% lines (gate 70%).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-09 23:50:41 -04:00

14 KiB

GSD Core 보안 모델

설명 — 이 문서는 GSD Core가 현재의 보안 자세를 갖는 이유와 계층들이 어떻게 맞물리는지를 설명한다. 모든 훅 파라미터에 대한 레퍼런스가 아니다. /gsd-secure-phase 명령과 옵션에 대해서는 명령어를 참조하라. 구현 수준의 훅 아키텍처에 대해서는 아키텍처 § 훅 시스템을 참조하라. 조직 전반의 보안 기준선(스캐너 제어, 인시던트 체크리스트, 소유권 모델)에 대해서는 SECURITY.md를 참조하라.


AI 기반 개발에 전용 보안 자세가 필요한 이유

일반적인 코드 에디터는 사용자를 대신하여 임의의 패키지를 실행하지 않는다. GSD Core는 그렇게 한다. 리서치 → 계획 → 실행 파이프라인은 "패키지 이름 지정"에서 "npm install <package> 실행"까지, "계획 결과물 작성"에서 "해당 결과물을 LLM 시스템 프롬프트로 사용"까지의 전체 경로를 자동화한다. 각 자동화 단계는 루프에서 사람을 제거한다 — 그리고 각 제거는 잠재적인 공격 표면이다.

GSD Core의 보안 모델은 하나의 조직 원칙을 중심으로 구축된다: 심층 방어(defence in depth). 어떤 단일 제어도 완벽하다고 가정하지 않는다. 여러 겹치는 계층이 각각 고유한 종류의 위험을 줄이며, 함께 공격 표면을 완전히 제거하지는 않지만 악용하기 상당히 더 어렵게 만든다. 이 문서 끝의 솔직한 요약은 시스템이 방어할 수 없는 것을 설명한다.


계층 1 — 공급망 보호: 패키지 적법성 게이트

위협

AI 모델은 패키지 이름을 환각한다. 이것은 변두리 실패 모드가 아니다: 2025년 연구에서 AI가 생성한 패키지 참조의 약 20%가 합법적인 패키지와 대응되지 않는 환각된 이름으로 문서화되었다. 그 환각된 이름들의 일부 — 같은 연구에서 약 43% — 는 프롬프트 전반에 걸쳐 일관되게 반복되며, 이는 공격자가 AI 도구들이 일반적으로 생성하는 이름을 관찰하고 악의적인 설치 후 스크립트로 npm, PyPI, 또는 crates.io에 해당 이름들을 선점 등록할 수 있다는 것을 의미한다. 이 기법을 *슬롭스쿼팅(slopsquatting)*이라고 한다.

슬롭스쿼팅의 교활한 특성은 npm view를 통과하는 환각된 이름이 합법적으로 보인다는 것이다. 레지스트리 항목은 누군가가 이름을 등록했다는 것만 증명한다 — AI가 말한 것을 패키지가 한다거나, 합법적인 사용자가 있다거나, 설치 스크립트가 안전하다는 것은 증명하지 않는다. 게이트 없이는 환각된 이름이 GSD의 리서처 → 플래너 → 실행기 파이프라인을 통해 감지되지 않고 흐르다가 결국 사용자의 기계에서 npm install <attacker-package>로 실행될 것이다.

게이트 작동 방식

게이트는 세 가지 파이프라인 단계에 걸쳐 작동한다:

리서치 단계. gsd-phase-researcher가 외부 패키지를 추천할 때 각 패키지에 대해 slopcheck install <pkgs> --json을 실행한다. 결과는 RESEARCH.md의 ## Package Legitimacy Audit 테이블에 작성된다. [SLOP]로 태그된 패키지들(높은 신뢰도의 환각 또는 공격자가 등록)은 파일이 저장되기 전에 RESEARCH.md에서 완전히 제거된다. 이런 패키지들은 절대 플래너에게 도달하지 않는다.

계획 단계. gsd-planner는 감사 테이블을 읽는다. [SUS](의심스러움: 최근 등록, 낮은 다운로드 수, 소스 저장소 없음, 또는 인기 있는 패키지와 가까운 명명 패턴)나 [ASSUMED](직접 레지스트리 검증이 아닌 WebSearch에서 출처)로 태그된 모든 패키지에 대해, 플래너는 설치 단계 전에 checkpoint:human-verify 작업을 삽입한다. 체크포인트에는 레지스트리 페이지로의 직접 링크와 살펴봐야 할 구체적인 항목들이 포함된다: 유지관리자 이력, 이슈 트래커 활동, 의심스러운 설치 스크립트의 부재.

실행 단계. 설치가 실패하면 gsd-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 설치 실패), GSD는 가장 엄격한 폴백을 적용한다: 모든 추천 패키지가 [ASSUMED]로 태그되고, 플래너는 모든 설치에 checkpoint:human-verify 작업을 게이트로 건다. 리서치와 계획 수립은 정상적으로 진행된다 — 시스템은 누락된 도구 의존성으로 인해 하드 실패하지 않는다. 이것은 의도적으로 정상 흐름보다 더 엄격하다: slopcheck 사용 불가는 모든 패키지 설치에 사람 체크포인트를 받는다는 것을 의미한다.

slopcheck 도구는 MIT 라이선스이며 pip으로 설치 가능하다. 유지 관리가 중단되더라도 [ASSUMED]-게이트 폴백은 사람 체크포인트 커버리지가 유지되도록 보장한다.


계층 2 — 프롬프트 인젝션 방어

위협

GSD Core는 LLM 시스템 프롬프트가 되는 마크다운 파일을 생성한다. 리서치 파이프라인은 외부 웹 콘텐츠를 읽는다; 계획 파이프라인은 사용자가 제공한 텍스트(--text-file, --prd)를 통합한다; 실행 파이프라인은 에이전트 컨텍스트로 나중에 다시 읽히는 계획 결과물을 작성한다. 이런 결과물들에 흐르는 사용자가 제어하는 텍스트는 잠재적인 간접 프롬프트 인젝션 벡터이다 — 시스템 프롬프트 안에 들어가면 에이전트의 지시 사항을 재정의하거나 정보를 유출하려는 공격자가 제어하는 문자열.

방어 작동 방식

GSD Core는 세 가지 수준에서 프롬프트 인젝션을 다룬다.

입력 유효성 검사(security.cjs). get-shit-done/bin/lib/security.cjs 모듈은 중앙 보안 유틸리티이다. 다음을 제공한다:

  • 경로 탐색 방지: 사용자가 제공한 파일 경로(--text-file, --prd)가 프로젝트 디렉터리 내에서 해결되도록 유효성이 검사되며, macOS의 /var → /private/var 심링크 해결이 명시적으로 처리된다
  • 프롬프트 인젝션 탐지: 알려진 인젝션 패턴(역할 재정의, 지시 우회, 시스템 태그 인젝션)이 사용자가 제공한 텍스트에서 계획 결과물에 들어가기 전에 스캔된다
  • 안전한 JSON 파싱: 제작된 JSON 페이로드를 통한 프로토타입 오염 공격을 방지하는 래퍼
  • 쉘 인수 유효성 검사: 하위 쉘 명령에 전달되는 인수가 사용 전에 유효성이 검사된다

런타임 훅: gsd-prompt-guard.js. 이 훅은 .planning/ 파일을 대상으로 하는 모든 Write 또는 Edit 호출에서 실행된다. 작성되는 콘텐츠를 security.cjs와 동일한 인젝션 패턴으로 스캔한다(독립성을 위해 훅에 직접 인라인된 하위 집합 — 훅은 모듈 경로가 변경되더라도 실행되도록 모듈을 require()하지 않는다). 탐지는 자문적 전용이다: 훅은 결과를 로그하지만 쓰기를 차단하지 않는다. 이유는 합법적인 계획 쓰기에 대한 오탐지 차단이 이차 스캔 계층에서 놓친 인젝션보다 더 방해가 될 것이기 때문이다.

런타임 훅: gsd-read-injection-scanner.js. 이 훅은 모든 Read 도구 호출의 출력에서 실행된다. 방금 읽은 콘텐츠를 신뢰할 수 없는 콘텐츠의 주입된 지시 사항으로 스캔한다 — 공격자가 GSD가 에이전트 컨텍스트에 통합하려는 파일에 지시 사항을 내장한 경우를 잡아낸다.

CI 스캐너. prompt-injection-scan.security.test.cjs는 테스트 스위트의 일부로 내장된 인젝션 벡터가 있는지 모든 에이전트, 워크플로우, 명령 파일을 스캔한다. 이는 GSD 소스 자체의 인젝션 시도를 잡아낸다 — 예를 들어 워크플로우 파일을 수정하여 역할 재정의 지시 사항을 추가하는 공급망 공격.

읽기 인젝션 스캐너 vs 프롬프트 가드

두 훅은 보완적인 표면을 커버한다. gsd-prompt-guard.js는 계획 결과물에 대한 쓰기를 감시한다 — 심어지는 인젝션을 잡는다. gsd-read-injection-scanner.js는 모든 파일의 읽기를 감시한다 — 외부 콘텐츠(의존성의 README, 타사 설정 파일, 사용자가 제공한 문서)에서 수집되는 인젝션을 잡는다. 함께 수집 → 저장 → 재독 수명 주기를 괄호로 묶는다.


계층 3 — 저장소 및 의존성 무결성

GSD의 런타임 동작 상류에서 open-gsd 조직은 저장소와 패키지 수준에서 제어를 시행한다. 이것들은 docs/security/baseline.md에 완전히 문서화되어 있으며 완전성을 위해 여기에 요약된다.

의존성 무결성. 모든 타사 의존성은 package-lock.json을 통해 고정되고 설치 전에 공개된 체크섬에 대해 검증된다. scripts/check-npm-integrity.cjs 게이트는 CI 시점에 유효하지 않은 버전, 누락된 패키지, 불필요한 패키지를 탐지한다. 이는 GSD 자체 의존성에 대한 의존성 혼동 및 오타스쿼팅 공격을 완화한다.

비밀 스캔. 모든 커밋과 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를 참조하라.


  • 명령어 — 보안 관련 플래그가 있는 /gsd-secure-phase와 /gsd-code-review 포함
  • 아키텍처 § 훅 시스템 — 모든 훅, 이벤트 트리거, 안전 속성에 대한 구현 상세
  • SECURITY.md — 취약점 신고, 조직 전반 보안 기준선, 비밀 스캔 제외 거버넌스, 의존성 무결성 검증
  • 문서 인덱스