16장 30일 도입 계획과 AI coding 규칙을 완성한다
1주차: inventory와 lockfile
핵심 service 세 개를 고르고 package manager와 lockfile 정책을 통일한다. repository owner와 production artifact를 연결한다. AI가 dependency를 추가할 때 이유·대안·version·license를 PR에 쓰게 한다.
2주차: SBOM과 dependency review
CI에서 SBOM을 만들고 component 수를 baseline으로 기록한다. 신규 dependency diff에 vulnerability와 license review를 붙인다. 아직 block하지 않고 false positive를 분류한다.
3주차: immutable artifact와 attestation
release artifact를 digest로 publish하고 approved workflow에서 provenance를 생성한다. 별도 verify job이 repository·ref·digest를 확인한다.
4주차: deployment policy와 incident rehearsal
staging에서 deny policy를 켠다. digest mismatch, unknown license, expired exception을 일부러 발생시켜 누가 어떻게 복구하는지 연습한다.
repository의 AI 작업 규칙 예시:
새 dependency는 승인 없이 추가하지 않는다.
manifest 변경에는 lockfile과 dependency rationale을 포함한다.
generated source도 test·lint·security·license gate를 통과한다.
CI permission을 확대하거나 mutable action tag를 추가하지 않는다.
release artifact는 approved workflow에서만 만들고 digest로 배포한다.
좋은 공급망 보안은 개발을 멈추게 하지 않는다. 검증된 기본 경로를 빠르게 만들고, 예외를 눈에 보이게 하며, 사고 때 영향을 몇 분 안에 찾게 한다.
부록 A 실습 정답과 파일 읽기
npm run scan 결과:
SCAN READY — 3 components, policy=deny, attestation=verified
deny와 verified가 동시에 나오는 것이 핵심이다. artifact의 출처가 맞아도 알려진 높은 위험 component 때문에 배포는 거절된다. 반대로 dependency policy가 깨끗해도 attestation이 다른 repository를 가리키면 거절해야 한다.
lab/output/:
sbom.cdx.json: component inventorypolicy-report.json: license·가상 vulnerability 판정artifact.bin: 고정 fixtureattestation.json: digest와 build identity claimverification.json: 실제 digest·repository·ref 검증
과제: policy.json에서 blockCvss만 높여 allow로 만들지 말고 old-parser version을 고친 새 lock fixture를 만든다. 보안 경고를 숨기는 것과 원인을 제거하는 것을 구분한다.
부록 B GitHub 확장 workflow
아래는 구조 예시다. action version은 공식 문서에서 최신 지원 version을 확인하고, 고위험 조직은 검토된 commit SHA pinning을 적용한다.
name: release
on:
push:
tags: ['v*']
permissions:
contents: read
id-token: write
attestations: write
packages: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@<REVIEWED_COMMIT_SHA>
- run: npm ci && npm test && npm run build
- name: Generate artifact attestation
uses: actions/attest@<REVIEWED_COMMIT_SHA>
with:
subject-path: dist/app.tgz
private repository 지원 plan, permission, attestation storage 조건은 조직 계정에서 확인한다. example을 그대로 production에 붙이지 않는다.
부록 C 트러블슈팅
| 증상 | 원인 후보 | 안전한 처리 |
|---|---|---|
| SBOM component가 0개 | lockfile format 불일치 | scanner version·package manager adapter 확인 |
| source와 image SBOM 수가 다름 | multi-stage·base OS·dev dependency | 둘의 목적을 구분하고 final artifact를 정본으로 연결 |
| vulnerability가 계속 재등장 | 오래된 artifact 재배포 | digest denylist와 promotion policy 적용 |
| signature는 통과, 배포는 거절 | repository·ref policy 불일치 | claim을 확인하고 우회 대신 승인 경로로 rebuild |
| digest mismatch | artifact 변경·잘못된 subject | artifact를 폐기하고 trusted build에서 재생성 |
| UNKNOWN license 다수 | metadata 부족·vendored code | source file review와 법무 triage, 무조건 allow 금지 |
| CI가 fork에서 secret 사용 | privileged event 설계 오류 | untrusted code와 credential job 분리 |
| emergency bypass가 남음 | TTL·owner 없음 | 자동 만료와 사후 incident review |
부록 D 저작권과 출간 안전성
원고·lab code·SVG는 이 책을 위해 독자적으로 작성했다. 표지 이미지는 외부 reference 없이 생성했고 provenance를 기록했다. old-parser, clean-schema, mystery-helper, DEMO-2026-0001은 학습용 가상 fixture이며 실제 package나 취약점 주장이 아니다.
공식 specification의 정의와 명령은 필요한 범위에서 설명하고 source URL을 research/SOURCES.md에 남겼다. 특정 vendor UI screenshot을 복제하지 않았다. 출간 전에는 공급망 보안 전문가, 오픈소스 법률 전문가가 각각 기술·라이선스 장을 검수하고 GitHub action 및 SLSA·CycloneDX version을 재확인한다.
부록 E 10일 공급망 방어 워크북
1일차 artifact 하나를 끝까지 추적한다
production에서 실행 중인 digest 하나를 고른다. source repository, commit, workflow run, SBOM, registry, environment, owner를 연결한다. 하나라도 찾지 못하면 unknown으로 남기고 owner를 배정한다.
2일차 dependency 변경을 재연한다
최근 package 추가 PR 하나를 고른다. manifest만 보지 말고 lockfile에서 direct·transitive 변화, install script, license, package 출처를 확인한다. “AI가 추천함”은 rationale로 인정하지 않는다.
3일차 SBOM 정확도 비교
source tree scanner와 final container scanner를 각각 실행한다. component 수가 다른 이유를 dev dependency, base OS, copied binary, multi-stage build로 분류한다. 어느 SBOM이 어느 digest에 대응하는지 metadata에 남긴다.
4일차 license triage
UNKNOWN 다섯 건을 선택해 package metadata와 source file header를 확인한다. 추측으로 SPDX ID를 채우지 않는다. 법무가 판단할 정보와 제품 배포 방식을 한 장에 모은다.
5일차 vulnerability context
높은 severity 한 건을 골라 runtime 포함, reachability, network exposure, data class, fix version을 조사한다. exception이 필요하면 owner·보완 통제·만료일을 넣는다.
6일차 workflow permission
release workflow의 job별 permission과 secret 접근을 표로 만든다. write-all, long-lived cloud key, untrusted fork code, mutable action reference를 찾는다. 가장 큰 credential 경계부터 줄인다.
7일차 attestation 실패 훈련
ChainLab의 attestation.json에서 repository, ref, digest를 하나씩 바꿔 본다. signature가 있다는 가정만으로 trust하지 않고 expected identity policy가 각 변조를 거절하는지 확인한다.
8일차 deployment gate observe mode
최근 20개 artifact에 policy를 read-only로 적용한다. false positive, 진짜 block, metadata 부족을 분류한다. owner와 고치는 link가 없는 경고는 enforce 전에 개선한다.
9일차 incident query
가상의 affected purl을 정하고 15분 안에 production artifact, environment, owner를 찾는다. source repository 검색만 사용하지 않는다. rollback artifact도 inventory에 있는지 본다.
10일차 release evidence bundle
artifact digest
source repository + commit
builder/workflow identity
SBOM + format version
policy report + exceptions
test summary
deployment environment + time
verification command and result
dependency PR template
## 추가 이유
표준 library·기존 dependency로 해결할 수 없는 이유:
## 출처와 유지보수
- 공식 registry/repository:
- publisher·maintainer 확인:
- release·support 신호:
## 공급망 변화
- direct/transitive component 변화:
- install script, license, known vulnerability:
## 제거와 rollback
- 제거 조건과 되돌릴 artifact:
배포 policy 의사코드
1. digest가 immutable하지 않으면 DENY
2. attestation subject와 실제 digest가 다르면 DENY
3. issuer·repository·workflow·ref가 allow policy와 다르면 DENY
4. SBOM subject가 같은 digest가 아니면 DENY
5. 유효 exception 없는 block finding이면 DENY
6. UNKNOWN license면 REVIEW
7. 나머지는 ALLOW하고 evidence ID를 deployment record에 저장
사고 대응 기록 template
# SUPPLY-INCIDENT-___
- advisory와 확인 시각:
- affected identity(purl/version):
- production artifact와 environment:
- reachability·exposure와 즉시 완화:
- fixed artifact digest:
- SBOM·attestation 검증 결과:
- 오래된 artifact 재배포 차단:
완료 기준은 scanner를 많이 설치하는 것이 아니다. production artifact 하나를 골랐을 때 재료, 제조 identity, 정책, 실행 위치, owner를 10분 안에 설명하고 변조된 artifact를 배포 전에 거절할 수 있어야 한다.
부록 F 캡스톤 통합 시나리오: AI가 추가한 package를 안전하게 출시한다
AI agent가 PDF text 추출을 위해 새 package와 600줄의 wrapper를 제안했다. feature는 동작하지만 lockfile에는 18개 transitive dependency가 늘었다. reviewer는 다음 순서로 처리한다.
1단계 필요성과 대안을 검토한다
표준 runtime 기능, 이미 설치된 library, 격리된 외부 service로 해결할 수 있는지 확인한다. 입력 PDF가 untrusted이므로 parser는 공격 표면이다. package를 application process 안에서 실행할지 sandbox worker로 분리할지도 결정한다.
2단계 identity와 변경 범위를 고정한다
공식 registry와 source repository, publisher, release tag를 대조한다. package name을 AI 응답에서 복사하지 않고 공식 registry에서 직접 확인한다. lockfile diff에서 install script와 native binary download가 있는지 본다.
3단계 두 SBOM을 만든다
source SBOM은 dependency review에, final image SBOM은 release inventory에 쓴다. 두 SBOM을 같은 것으로 덮어쓰지 않는다. final image에서 예상하지 못한 OS package가 추가됐다면 base image 변경부터 추적한다.
4단계 policy를 적용한다
license가 허용 범위인지, notice가 필요한지, known vulnerability와 exploit signal이 있는지 본다. parser code가 실제로 vulnerable path를 호출하는지 reachability를 조사하되, 불확실성을 이유로 높은 위험을 무시하지 않는다.
5단계 격리와 test를 증거로 만든다
malformed fixture, 큰 file, timeout, password-protected PDF, zip bomb 유사 크기 제한을 방어적으로 test한다. network와 filesystem permission을 최소화하고 CPU·memory·time limit을 둔다. 책은 실제 공격 payload를 제공하지 않고 경계와 expected failure만 검증한다.
6단계 approved workflow에서 build한다
protected branch의 reviewed commit만 release workflow가 읽는다. workflow는 clean ephemeral runner에서 test·SBOM·build를 실행하고 immutable digest를 publish한다. 장기 registry key 대신 가능한 범위에서 짧은 수명 identity를 쓴다.
7단계 attestation과 deployment gate
attestation subject digest가 실제 artifact와 일치하고 repository, workflow, ref가 allow policy에 맞는지 별도 job에서 검증한다. SBOM도 같은 digest를 가리켜야 한다. 한 조건이라도 다르면 새 build로 돌아가며 report file을 손으로 수정하지 않는다.
8단계 release 뒤 운영한다
release record에 digest, component purl, owner, environment를 저장한다. 새 advisory가 나오면 source code grep이 아니라 production inventory를 query한다. parser 장애율과 timeout을 service SLO에 연결한다.
PR decision: approve with sandbox boundary
artifact: sha256:<actual digest>
SBOM: final image digest와 연결
policy: allow, UNKNOWN 0, exception 0
provenance: approved repository/workflow/main
deployment: staging canary → production
rollback: 이전 검증 digest
장별 산출물 지도
| 장 | 독자가 남길 산출물 |
|---|---|
| 1–2 | AI 변경 review 규칙과 자산 흐름 위협 모델 |
| 3–4 | lockfile 정책과 신규 package checklist |
| 5–6 | 검증된 SBOM과 format 선택 기록 |
| 7–8 | 취약점·license policy와 만료되는 exception |
| 9–10 | secret incident runbook과 최소 권한 workflow |
| 11–13 | immutable digest·attestation·SLSA gap 분석 |
| 14–15 | deployment gate와 searchable incident inventory |
| 16 | 30일 rollout과 repository AI 작업 규칙 |