EROKE ORIGINAL WEBBOOK

AI가 만든 코드, 공급망까지 안전합니까

AI가 만든 코드, 공급망까지 안전합니까 웹북 표지
전체 목차16개 장
  1. AI가 만든 코드, 공급망까지 안전합니까: 1장 AI가 코드를 썼다는 사실은 새로운 신뢰 경계다
  2. AI가 만든 코드, 공급망까지 안전합니까: 2장 위협 모델은 공격자 목록이 아니라 자산 흐름이다
  3. AI가 만든 코드, 공급망까지 안전합니까: 3장 manifest와 lockfile을 구분한다
  4. AI가 만든 코드, 공급망까지 안전합니까: 4장 package 이름을 믿지 않고 출처를 확인한다
  5. AI가 만든 코드, 공급망까지 안전합니까: 5장 SBOM을 생성하고 먼저 정확도를 의심한다
  6. AI가 만든 코드, 공급망까지 안전합니까: 6장 CycloneDX와 SPDX를 목적에 맞게 선택한다
  7. AI가 만든 코드, 공급망까지 안전합니까: 7장 취약점 숫자를 배포 결정으로 번역한다
  8. AI가 만든 코드, 공급망까지 안전합니까: 8장 license는 scanner 경고가 아니라 배포 의무다
  9. AI가 만든 코드, 공급망까지 안전합니까: 9장 secret은 source에 들어오기 전에 막는다
  10. AI가 만든 코드, 공급망까지 안전합니까: 10장 CI workflow 자체도 dependency다
  11. AI가 만든 코드, 공급망까지 안전합니까: 11장 artifact를 tag가 아니라 digest로 식별한다
  12. AI가 만든 코드, 공급망까지 안전합니까: 12장 attestation은 서명이 아니라 주장과 identity의 결합이다
  13. AI가 만든 코드, 공급망까지 안전합니까: 13장 SLSA를 badge가 아니라 개선 경로로 쓴다
  14. AI가 만든 코드, 공급망까지 안전합니까: 14장 검증된 artifact만 배포하는 gate를 만든다
  15. AI가 만든 코드, 공급망까지 안전합니까: 15장 사고가 나면 SBOM을 검색 가능한 운영 자산으로 쓴다
  16. AI가 만든 코드, 공급망까지 안전합니까: 16장 30일 도입 계획과 AI coding 규칙을 완성한다

SBOM·라이선스·취약점·서명·출처 증명으로 완성하는 안전한 배포

ChainLab으로 lockfile, SBOM, 라이선스·취약점 정책, artifact digest와 attestation을 연결해 검증된 배포를 만든다.

상태: 출간 후보 웹교정쇄 · 공급망 보안·오픈소스 법률 감수 대기 · 16개 장

AI coding agent는 몇 분 만에 기능과 dependency를 추가한다. 그러나 “build가 성공했다”는 사실은 이 결과를 배포해도 된다는 뜻이 아니다. 어떤 source에서, 어떤 dependency와 instruction으로, 어느 runner가 만든 artifact인지 설명하지 못하면 우리는 파일을 받은 것이지 신뢰를 얻은 것이 아니다.

이 책은 보안 제품 목록이 아니다. 가상의 고객지원 서비스 HelpDesk AI를 대상으로 lockfile에서 SBOM을 만들고, 라이선스와 알려진 위험 정책을 적용하고, artifact digest와 build identity를 검증해 배포 허용 여부를 결정한다. 기본 실습은 외부 network 없이 고정 fixture로 재현되며, 확장 실습은 GitHub artifact attestation과 Sigstore, SLSA 원칙으로 이어진다.

source부터 검증된 artifact까지 이어지는 독창적인 공급망 표지 비주얼
source부터 검증된 artifact까지 이어지는 독창적인 공급망 표지 비주얼

이 책을 마치면 다음을 할 수 있다.

  1. AI가 제안한 package를 이름만 보고 설치하지 않고 변경 이유와 maintainer 신호를 검토한다.
  2. manifest와 lockfile의 차이를 설명하고 재현 가능한 install을 만든다.
  3. CycloneDX 또는 SPDX SBOM을 만들고 정확도와 완전성을 확인한다.
  4. 취약점 severity, exploitability, reachability, 배포 환경을 함께 판단한다.
  5. 라이선스 식별·notice·source 제공 의무를 release gate로 연결한다.
  6. secret, prompt, generated code provenance를 안전한 review 흐름에 넣는다.
  7. artifact digest와 attestation의 builder identity를 검증한다.
  8. 검증된 artifact만 staging·production에 들어가게 admission policy를 설계한다.

SBOM은 재료표이고 attestation은 제조 증명이다. 둘 중 하나만으로 안전을 보장하지 않는다. 재료를 알아도 누가 만들었는지 모를 수 있고, 승인된 builder가 취약한 재료를 쓸 수도 있다.


cd /Users/honi/WithAI/books/secure-ai-software-supply-chain
npm test
npm run scan
npm run lab

http://127.0.0.1:4312를 열면 source→lock→SBOM→policy→attest→verify 여섯 단계가 보인다. 의도적으로 old-parser에는 높은 가상 취약점이, mystery-helper에는 알 수 없는 license가 설정되어 있다. 실제 package에 대한 주장이 아니다.

이 책의 실제 ChainLab 실습 화면
이 책의 실제 ChainLab 실습 화면

1장 AI가 코드를 썼다는 사실은 새로운 신뢰 경계다

사람이 직접 입력했든 AI가 생성했든 code review 기준은 같아야 한다. 하지만 AI는 그럴듯한 package 이름, 존재하지 않는 option, 오래된 API를 자신 있게 제안할 수 있고, 한 번에 넓은 범위를 바꾼다. 속도가 빨라진 만큼 검증되지 않은 변화가 쌓이는 속도도 빨라진다.

AI 생성 code를 별도 낙인처럼 취급하지 않는다. 대신 모든 변화에 같은 증거를 요구한다.

질문 필요한 증거
왜 바꿨나 issue·acceptance criteria·decision log
무엇이 바뀌었나 diff·dependency review·generated files
동작하나 test·reproduction·expected output
안전한가 SAST·secret·dependency·license policy
무엇을 배포하나 immutable digest·SBOM
어디서 만들었나 signed provenance·builder identity

AI 대화 기록 전체를 공급망 증거로 보관할 필요는 없다. 민감한 prompt가 섞일 수 있고 model UI export는 재현 가능한 build instruction이 아니다. repository에는 승인된 spec, source, lockfile, test, build workflow를 정본으로 둔다.

↑ 목차로 돌아가기

2장 위협 모델은 공격자 목록이 아니라 자산 흐름이다

공급망 위협을 “악성 package” 하나로 좁히면 중요한 경계를 놓친다. HelpDesk AI의 흐름을 그린다.


개발자/AI → source branch → pull request → dependency registry
          → CI runner → build artifact → registry → deployment controller
          → runtime cluster

각 화살표에서 identity, integrity, authorization을 묻는다.

  • 누가 branch에 push할 수 있는가?
  • pull request review를 우회할 수 있는가?
  • package 이름이 dependency confusion에 노출되는가?
  • CI가 외부 fork의 code와 secret을 함께 실행하는가?
  • action을 mutable tag로 가져오는가?
  • artifact tag가 다른 digest로 바뀔 수 있는가?
  • deployment가 attestation을 실제로 검증하는가?

위협 모델 표에는 자산, actor, 경계, 실패, 방어, evidence owner를 넣는다. “해커가 침입한다” 대신 “untrusted pull request가 privileged runner에서 실행되어 release credential에 접근한다”처럼 검증 가능한 문장으로 쓴다.

↑ 목차로 돌아가기

3장 manifest와 lockfile을 구분한다

package.json의 version range는 허용 범위를 표현한다. lockfile은 실제로 해석된 version과 transitive dependency를 고정한다. source만 같고 lockfile이 다르면 다른 artifact가 나올 수 있다.

실습 fixture:


"node_modules/clean-schema": {
  "version": "2.1.0",
  "license": "MIT"
}

CI에서는 clean install을 사용하고 lockfile 변경을 review한다. dependency를 추가했는데 lockfile이 바뀌지 않았거나, 사소한 수정인데 수백 package가 변경되면 이유를 확인한다. AI에게 “오류 고쳐 줘”라고 했더니 package manager를 바꾸거나 lockfile을 재생성하는 경우가 있다.

검토 순서:

  1. direct dependency를 왜 추가했는가?
  2. 표준 library나 기존 dependency로 해결할 수 없는가?
  3. package의 공식 registry·repository·maintainer가 일치하는가?
  4. transitive dependency 수와 install script가 늘었는가?
  5. version과 integrity가 lockfile에 고정됐는가?
  6. license와 지원 수명은 조직 정책에 맞는가?

↑ 목차로 돌아가기

4장 package 이름을 믿지 않고 출처를 확인한다

AI가 추천한 package를 바로 설치하지 않는다. 오타가 비슷한 typosquatting, 내부 package와 같은 이름을 public registry에서 먼저 찾는 dependency confusion, 탈취된 maintainer 계정이 있을 수 있다.

확인 checklist:

  • package registry의 publisher와 linked source repository
  • 최근 release와 security advisory
  • repository tag와 배포 package version의 대응
  • install·postinstall script
  • maintainer 변경과 갑작스러운 ownership 이동
  • 조직 내부 namespace와 registry 우선순위

download 수는 인기 신호이지 안전 증명이 아니다. 별점, README 품질, AI의 설명도 검증을 대체하지 못한다. 새 dependency 요청에는 owner와 제거 계획을 남긴다. 기능 하나 때문에 들어온 package는 기능을 삭제해도 남기 쉽다.

↑ 목차로 돌아가기

5장 SBOM을 생성하고 먼저 정확도를 의심한다

SBOM은 software component와 관계를 machine-readable format으로 기록한다. CISA 등 여러 기관의 공동 지침은 SBOM을 software 공급망 투명성을 위한 재료표로 설명하고 자동 생성·활용을 강조한다. 하지만 tool이 파일을 만들었다고 정확한 것은 아니다.

npm run scan은 lockfile에서 세 component를 뽑아 lab/output/sbom.cdx.json을 만든다.


{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "components": [{
    "type": "library",
    "name": "clean-schema",
    "version": "2.1.0",
    "purl": "pkg:npm/clean-schema@2.1.0"
  }]
}

확인할 품질:

  • root application identity가 있는가?
  • direct와 transitive component가 빠지지 않았는가?
  • name·version·purl이 registry와 맞는가?
  • build 안에 들어가지 않는 dev dependency를 구분하는가?
  • container OS package와 binary도 포함되는가?
  • SBOM이 어느 artifact digest에 대응하는가?

source SBOM과 final container SBOM은 다를 수 있다. multi-stage build, copied binary, base image package까지 보려면 final artifact를 scan해야 한다.

↑ 목차로 돌아가기

6장 CycloneDX와 SPDX를 목적에 맞게 선택한다

둘 다 널리 쓰이는 공개 format이다. 특정 format이 무조건 우월하다고 말하기보다 consumer가 무엇을 읽을 수 있는지 본다. 보안 toolchain이 CycloneDX를 요구하고 법무 교환이 SPDX를 요구할 수 있다.

선택 질문:

  • 고객·정부 조달이 요구하는 format과 version은 무엇인가?
  • component relationship과 vulnerability data를 어떤 tool이 소비하는가?
  • license expression과 notice 생성 흐름은 무엇인가?
  • registry와 attestation system이 어느 predicate를 지원하는가?

가능하면 build에서 canonical inventory 하나를 만들고 필요한 format으로 export한다. 서로 다른 scanner가 별도 목록을 만들면 component 수가 달라져 감사 때 혼란이 생긴다. conversion 뒤 component identity와 dependency 관계가 보존됐는지 test한다.

↑ 목차로 돌아가기

7장 취약점 숫자를 배포 결정으로 번역한다

CVSS가 높다고 모든 환경에서 즉시 exploit되는 것은 아니고, 낮다고 무시할 수도 없다. component가 runtime에 포함되는지, vulnerable function에 도달하는지, 외부에 노출되는지, 알려진 exploit이 있는지, 보완 통제가 있는지를 함께 본다.

실습 policy는 단순히 CVSS 7 이상을 block한다. 학습용 시작점일 뿐 운영 policy는 다음 context를 추가한다.


severity + exploit maturity + reachability + runtime exposure
+ data sensitivity + fix availability + business deadline

exception에는 만료일이 필요하다.


exception_id: SEC-2026-041
component: example@1.2.3
reason: fixed version breaks required protocol
compensating_control: endpoint disabled and network restricted
owner: team-support
expires_at: 2026-09-01

만료 없는 allowlist는 영구 우회로가 된다. exception이 만료되면 build가 자동 실패하거나 재승인을 요구한다.

↑ 목차로 돌아가기

8장 license는 scanner 경고가 아니라 배포 의무다

license scanner가 MIT라고 표시해도 package 안의 file별 license나 bundled asset이 다를 수 있다. UNKNOWN은 “문제 없음”이 아니라 조사되지 않음이다. 조직 정책은 법률 자문과 제품 배포 방식에 맞춰 만든다.

일반 절차:

  1. component와 실제 배포 여부를 식별한다.
  2. SPDX expression을 가능한 범위에서 정규화한다.
  3. notice·copyright·source 제공 등 의무를 법무와 분류한다.
  4. 배포 package에 notice를 생성한다.
  5. 알 수 없거나 상충하는 license는 사람 review로 보낸다.

AI가 생성한 code에 “license 문제 없다”고 단정하게 하지 않는다. 학습 data의 개별 출처를 AI가 증명할 수 없고, 생성 결과가 기존 code와 우연히 유사할 수 있다. 비정상적으로 구체적이고 긴 code가 생성되면 검색과 사람이 검토한다. third-party snippet을 prompt로 넣었다면 원출처와 license를 별도 기록한다.

↑ 목차로 돌아가기

9장 secret은 source에 들어오기 전에 막는다

API key가 commit된 뒤 삭제해도 Git history와 fork, CI log, cache에 남을 수 있다. 가장 좋은 대응은 commit 전 차단과 짧은 수명의 credential이다.

  • local pre-commit은 빠른 feedback
  • server-side secret scanning은 우회 방지
  • CI OIDC는 장기 cloud key를 줄임
  • environment approval은 production credential 접근 통제
  • log redaction은 사고 범위 축소

secret이 발견되면 file 삭제보다 먼저 revoke·rotate한다. 다음으로 history와 artifact, log 노출 범위를 조사한다. 실제 key를 test fixture로 쓰지 않는다. sk_demo_not_real처럼 명백한 placeholder도 scanner rule을 test할 때만 격리한다.

↑ 목차로 돌아가기

10장 CI workflow 자체도 dependency다

application dependency만 scan하고 action과 runner image를 놓치기 쉽다. uses: owner/action@v4 같은 tag는 편하지만 tag가 움직일 수 있다. 고위험 release workflow는 검토된 commit SHA에 pin하고 자동 업데이트 PR로 유지한다.

workflow 최소 권한:


permissions:
  contents: read
  id-token: write
  attestations: write

모든 job에 write-all을 주지 않는다. fork pull request에서 untrusted code를 privileged context로 실행하지 않는다. self-hosted runner는 이전 job의 file과 credential이 남지 않게 ephemeral하게 운영한다.

third-party action도 source repository, release, maintainer, dependency를 가진 software다. SBOM과 inventory에 CI component를 포함하는 이유다.

↑ 목차로 돌아가기

11장 artifact를 tag가 아니라 digest로 식별한다

app:latestapp:1.2 tag는 다른 image를 가리키도록 바뀔 수 있다. digest는 content hash이므로 같은 bytes는 같은 identity를 가진다.

실습은 artifact.bin의 SHA-256을 계산한다.


const digest = createHash('sha256').update(artifact).digest('hex');

build가 만든 digest를 deployment manifest에 기록하고 promotion 때 다시 build하지 않는다. staging에서 검증한 artifact와 production artifact가 같아야 한다. environment별 설정은 외부 주입하되 executable artifact는 그대로 승격한다.

hash는 누가 만들었는지를 말해 주지 않는다. 공격자가 악성 artifact의 hash를 함께 바꿀 수 있다. 그래서 digest를 신뢰할 수 있는 identity가 서명한 attestation과 연결한다.

↑ 목차로 돌아가기

12장 attestation은 서명이 아니라 주장과 identity의 결합이다

attestation은 artifact에 대한 구조화된 주장이다. subject digest, source repository, commit, workflow, builder 같은 정보를 포함할 수 있다. signature 검증만 통과했다고 끝나지 않는다. 어떤 identity가 어떤 조건에서 서명했는지 policy로 확인한다.

ChainLab의 verifyAttestation은 세 조건을 본다.


subject digest == 실제 artifact digest
repository == withai/helpdesk-ai
ref == refs/heads/main

운영에서는 reusable workflow identity, environment, event, issuer, transparency log 또는 조직 trust root를 확인한다. GitHub artifact attestation은 build가 어디서 어떻게 만들어졌는지 provenance를 세우며, workflow에 id-token, contents, attestations permission이 필요하다. 지원 plan과 private repository 범위는 적용 시점 공식 문서를 확인한다.

↑ 목차로 돌아가기

13장 SLSA를 badge가 아니라 개선 경로로 쓴다

SLSA는 software artifact 공급망의 integrity 수준을 높이기 위한 specification과 track을 제공한다. 숫자만 badge로 붙이지 말고 현재 build에서 빠진 보장을 찾는 checklist로 쓴다.

질문:

  • build process가 version-controlled definition에서 시작하는가?
  • provenance가 artifact와 연결되는가?
  • build service가 provenance를 위조하기 어렵게 생성하는가?
  • source와 build platform 접근이 통제되는가?
  • 소비자가 provenance를 실제 검증하는가?

level 주장을 marketing 문구로 쓰기 전에 해당 SLSA version의 요구와 artifact 종류, builder를 명시한다. attestation 생성만 하고 deployment가 검증하지 않으면 실질 보호가 없다.

↑ 목차로 돌아가기

14장 검증된 artifact만 배포하는 gate를 만든다

pipeline 마지막에 report를 만들고 사람이 보지 않으면 경고는 쌓이기만 한다. 배포 controller 앞에서 machine-readable policy로 결정한다.


deny if digest is mutable or absent
deny if provenance repository is not approved
deny if build ref is not protected main or release tag
deny if critical runtime vulnerability has no valid exception
review if license is unknown
allow only when SBOM and attestation match the same digest

처음부터 production을 block하면 false positive 때문에 policy가 제거될 수 있다. 1단계 observe, 2단계 warning과 owner 배정, 3단계 신규 service block, 4단계 전체 enforce로 간다. emergency bypass에는 2인 승인, 짧은 TTL, 사후 review가 필요하다.

source·SBOM·정책·attestation을 연결하는 배포 증거 사슬
source·SBOM·정책·attestation을 연결하는 배포 증거 사슬

↑ 목차로 돌아가기

15장 사고가 나면 SBOM을 검색 가능한 운영 자산으로 쓴다

새 취약점이 공개됐을 때 “어느 repository가 package를 썼나?”보다 “어느 production artifact에 실제 포함됐고 누가 owner인가?”가 중요하다. SBOM을 release digest, service catalog, deployment environment와 연결한다.

사고 query:


purl = affected component
AND environment = production
AND deployment_status = running
AND exception_status != mitigated

대응 순서:

  1. affected version 범위를 공식 advisory에서 확인한다.
  2. SBOM inventory로 candidate artifact를 찾는다.
  3. runtime reachability와 exposure로 우선순위를 정한다.
  4. owner에게 fix 또는 mitigation deadline을 배정한다.
  5. 새 artifact의 SBOM·attestation을 검증하고 승격한다.
  6. 오래된 vulnerable artifact 재배포를 policy로 막는다.

SBOM을 release 때 만들고 버리면 사고 때 쓸 수 없다. search 가능한 repository와 retention, access control을 운영한다.

↑ 목차로 돌아가기

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

denyverified가 동시에 나오는 것이 핵심이다. artifact의 출처가 맞아도 알려진 높은 위험 component 때문에 배포는 거절된다. 반대로 dependency policy가 깨끗해도 attestation이 다른 repository를 가리키면 거절해야 한다.

lab/output/:

  • sbom.cdx.json: component inventory
  • policy-report.json: license·가상 vulnerability 판정
  • artifact.bin: 고정 fixture
  • attestation.json: digest와 build identity claim
  • verification.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 작업 규칙

↑ 목차로 돌아가기

공식 참고 자료

기술·가격·정책은 바뀔 수 있으므로 실제 적용 전에 아래 원문을 다시 확인하세요.