Files
2nd/10_Wiki/Topics/Coding/DevSec_Supply_Chain.md
T
2026-05-09 21:08:02 +09:00

6.4 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
devsec-supply-chain Supply Chain Security — SBOM / Sigstore / Provenance Coding draft B conceptual 2026-05-09 2026-05-09
devsecops
supply-chain
sbom
sigstore
vibe-coding
language applicable_to
OSS / CI
DevOps
SBOM
Sigstore
cosign
SLSA
provenance
npm audit
dependency confusion

Supply Chain Security

Log4Shell / xz / event-stream — 의존성이 공격 통로. SBOM (재고) + Sigstore (서명) + SLSA (출처) + 자동 update. xz 같은 sneak attack 방어.

📖 핵심 개념

  • SBOM: 모든 의존성 list.
  • Sigstore: 서명 + transparency log.
  • SLSA: provenance 표준 (build 환경 attest).
  • Dependency confusion: public / private 같은 이름 충돌.

💻 코드 패턴

npm audit (기본)

npm audit              # 알려진 CVE
npm audit fix          # 자동 patch (minor)
npm audit --production # prod 만

Snyk / Dependabot

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule: { interval: "weekly" }
    open-pull-requests-limit: 5
    groups:
      production-dependencies:
        dependency-type: "production"
      development-dependencies:
        dependency-type: "development"

→ 자동 PR + CVE patch.

SBOM 생성

# CycloneDX (npm)
npx @cyclonedx/cyclonedx-npm --output-format JSON > sbom.json

# Syft (any)
syft . -o cyclonedx-json > sbom.json
syft . -o spdx-json > sbom-spdx.json

# Container
syft myapp:latest -o cyclonedx-json > sbom.json

→ Compliance / 사고 시 추적.

SBOM scan (CVE 검사)

# Grype 가 SBOM 직접 검사
grype sbom:./sbom.json

Cosign (Sigstore signing)

# Keyless (OIDC, GitHub Actions)
cosign sign $REGISTRY/myapp:$TAG --yes

# Verify
cosign verify $REGISTRY/myapp:$TAG \
  --certificate-identity 'https://github.com/myorg/myrepo/.github/workflows/release.yml@refs/heads/main' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com'

→ 누가 / 어떤 commit 으로 build 했는지 검증.

SLSA provenance (build attestation)

# .github/workflows/release.yml
permissions:
  id-token: write
  contents: read
  attestations: write

steps:
  - uses: docker/build-push-action@v5
    with:
      provenance: mode=max
      sbom: true
      
  - uses: actions/attest-build-provenance@v1
    with:
      subject-name: ghcr.io/myorg/myapp
      subject-digest: ${{ steps.build.outputs.digest }}

→ Build 환경 자동 attest.

npm package — provenance

# 자동 cosign signing
- run: npm publish --provenance
  env: { NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} }
# 사용자 측
npm install <pkg> --foreground-scripts=false

Lockfile 강제

# CI
- run: npm ci   # not npm install — lockfile 정확
- run: yarn install --immutable
- run: pnpm install --frozen-lockfile

→ Lockfile 변경 시 CI 가 fail.

Postinstall script 차단 (위험)

# Worst case: 악성 postinstall
npm install --ignore-scripts

# package.json 으로
{
  "preinstall": "npx only-allow pnpm",  // Yarn / npm 차단
}

Allowlist (private registry)

# .npmrc
@mycompany:registry=https://npm.mycompany.com

# 그 외 = 외부 registry
registry=https://registry.npmjs.org/

→ Public 에 같은 이름 (@mycompany/lib) 등록 = dependency confusion.

// package.json — name 충돌 차단
{
  "name": "@mycompany/myapp",
  // public 에 가짜 등록 시 npm 가 우선 lookup → leak
  // → private registry 만 사용
}

Verify dependencies

# 인기 도구
npx good-fences  # boundary
npx knip         # unused
npx depcheck     # unused
npx better-npm-audit
npx ls-engines    # node version compat

NPM token (CI / publish)

- Granular access tokens (특정 package 만)
- 짧은 expiry
- Repo secret 으로 (env 노출 X)

License 검사

license-checker --production --summary
license-checker --excludePackages 'mit;apache-2.0' --failOn 'gpl-3.0;agpl-3.0'

→ AGPL 같은 라이센스 prod 차단 (회사 정책).

Vulnerability triage

1. CVSS score 검토 (Critical, High)
2. 실제 attack vector 가능?
   - Local only? Network? Auth required?
3. 사용 경로 — 이 lib 의 vulnerable function 우리가 사용?
4. Patch 가능 여부
   - Minor → 자동
   - Major → manual review
   - 없음 → workaround / fork / replace

xz-style attack (long-term sneak)

2024 xz 백도어 — 긴 시간 contributor build trust.

방어:
- 새 contributor 코드 review 강
- Build script 변경 의심
- Reproducible build (다른 환경 같은 hash)
- Binary diff vs source
- Sigstore + SLSA = build provenance 검증

Reproducible build

# 시간 / random 제거
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN SOURCE_DATE_EPOCH=$(date -d "2024-01-01" +%s) npm ci
RUN find . -newer /app -exec touch -d "@$SOURCE_DATE_EPOCH" {} +

→ 같은 source = 같은 binary hash.

정책 (CI)

- name: Audit
  run: npm audit --audit-level=high
  
- name: License check
  run: license-checker --excludePackages '...' --failOn 'GPL-3.0;AGPL-3.0'

- name: SBOM
  run: syft . -o cyclonedx-json > sbom.json
  
- uses: actions/upload-artifact@v4
  with: { name: sbom, path: sbom.json }

Compromised package detect

Socket.dev / Snyk 가 새 release 자동 분석 (suspicious behavior).
- Network call 새로
- File system access 새로
- Postinstall 새로

🤔 의사결정 기준

작업 추천
자동 patch Dependabot
CVE 모니터링 Snyk / GitHub Advanced Security
SBOM Syft (open)
Signing Cosign (Sigstore)
Provenance SLSA via GitHub attest
Suspicious detect Socket.dev

안티패턴

  • Lockfile 무시: npm install prod build.
  • Audit ignore high: 알면서 무시.
  • Postinstall 모두 허용: 임의 코드.
  • Latest tag: 새 release 가 깨짐.
  • Private + public 같은 이름: dependency confusion.
  • NPM token long-lived: leak 시 큰 영향.
  • Build attestation 없음: 출처 검증 X.

🤖 LLM 활용 힌트

  • Lockfile + Dependabot + npm audit + SBOM.
  • Cosign + SLSA = supply chain integrity.
  • Private registry + scoped packages.

🔗 관련 문서