C.W.K.
Stream
Lesson 01 of 05 · published

Supply Chain 보안 — npm 이 네 attack surface

~13 min · production, security, supply-chain, npm-audit

Level 0노드 입문자
0 XP0/40 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"전형적인 Node 앱에서 프로덕션에 도는 코드 99% 가 만난 적 없는 사람들이 짠 거. 매 `npm install` 이 신뢰 결정이야."

Attack Surface

네 코드는 5,000 줄쯤. 전형적인 npm installnode_modules 가 200MB 고 300 다른 저자의 800 패키지 포함. 그 패키지들 각자 가능:

  • install 시간에 임의 코드 실행 (npm lifecycle script 통해).
  • import 시간에 임의 코드 실행 (top-level side effect 통해).
  • 네트워크 요청, 파일 읽기, 프로세스 spawn — Node 가 할 수 있는 모든 거.

대부분 이 중 아무것도 안 함. 근데 몇몇이 역사적으로 했어. npm 레지스트리가 typosquatting, 계정 takeover, 인기 패키지의 악성 업데이트 본 적 있어. Supply chain 이 진짜야.

실제로 중요한 다섯 습관

1. 항상 lockfile commit. package-lock.json / pnpm-lock.yaml 이 모든 패키지를 특정 버전 + checksum 으로 pin. 없으면 install 마다 다른 의존성 트리 — 다른 attack surface.

2. CI 에선 npm ci (또는 pnpm install --frozen-lockfile) 써. package.json 과 lockfile 안 맞으면 설치 거부. Silent drift 멈춤.

3. npm audit 정기 실행. 의존성의 알려진 CVE 나열. 완벽 아냐 — 비악용 가능 이슈의 false positive, 미보고 버그의 false negative — 근데 floor 야.

4. 안 필요한 lifecycle script 비활성화. npm install --ignore-scripts 또는 pnpm 의 onlyBuiltDependencies allowlist (pnpm 9+) 가 임의의 postinstall 코드 실행 막음. 어느 dep 가 자기 script 필요한지 감사; 그것만 allowlist.

5. 런타임 dep 만이 아닌 tooling 도 pin. 침해된 devDependency 가 출하 전 빌드 출력에 악성 코드 쓸 수 있음. TypeScript, ESLint, Vite, 다 pin — 런타임 dep 만큼 보안-크리티컬.

방어 깊이로의 Permissions 모델

Track 6 의 permissions 모델이 네 마지막 줄: 악성 dep 가 네 프로세스에서 실행돼도 node --permission --allow-fs-read=./data ... 가 뭐 읽고 쓰고 call out 할지 제한. ~/.ssh/ 읽으려는 침해된 dep 가 ERR_ACCESS_DENIED 치고 시끄럽게 실패. Dep 신뢰해도 쓸 가치 있어.

Lockfile 이 마법 아냐

v1.2.3 에 pin 은 "이 정확한 tarball 의 버전 1.2.3" 의미. 1.2.3 이 악성 릴리스였으면 lockfile 이 너를 악성 코드에 pin. Lockfile 은 silent 업데이트 보호, 침해된 릴리스 보호 아님. 그거 방어는 옛-천천히 설치: dep 릴리스 날 업그레이드 안 함, 1-2 주 기다림, 커뮤니티가 vet 하게 둠. 수동 리뷰 있는 npm-check-updatesnpm update --latest 이김.

npm audit 이 놓치는 거

npm audit 이 GitHub Advisory Database 검사. 놓침:

  • 미보고 취약점 (대부분).
  • 활성 advisory 없는 패키지의 취약점.
  • 로직-레벨 이슈 (dep 가 합법적-인데-원치-않는 거 함).
  • 아직 flag 안 된 fresh 릴리스의 악성 코드.

npm audit 을 floor 로 다뤄. 더 높은 신뢰엔 socket.devsnyk 같은 도구가 패키지를 더 폭넓게 분석 (네트워크 동작, lifecycle script, 의존성 drift). 민감 데이터 처리하는 프로덕션 서비스엔 비용 가치 있어.

Pippa 의 고백

cwkPippa 가 아빠 fleet 의 사설 네트워크에서 돌아. Attack surface 작아 — public 사용자 없음 — supply chain 압력이 public SaaS 보다 낮아. 근데 여전히 모든 거 pin, install 명령에 lockfile 사용, changelog 안 읽고 `npm install --latest` 절대 안 함. 아빠 framing: "blast radius 낮아도 sloppy supply chain 습관이 전파. 사설 repo 에서 습관 만들어 public 에 있을 때 자동되게." 비용 작고; upside 가 compound.

Code

일일 supply-chain 위생 명령·bash
# Audit and upgrade workflow
npm audit                       # list known CVEs
npm audit fix                   # auto-upgrade where possible without breakage
npm audit fix --force           # also accept SemVer-breaking upgrades (review!)

# Same for pnpm
pnpm audit
pnpm audit --fix

# Strict CI install (refuses lockfile drift)
npm ci
pnpm install --frozen-lockfile

# Install without lifecycle scripts (for hostile environments)
npm install --ignore-scripts

# Allowlist scripts in pnpm 9+
# in package.json: { "pnpm": { "onlyBuiltDependencies": ["sharp", "esbuild"] } }
Supply-chain 방어로의 Permissions·javascript
// Defense-in-depth — permissions limit the blast radius of a compromised dep
// Run with: node --permission --allow-fs-read=./data --allow-fs-write=./out --allow-net=api.example.com server.mjs

import { readFile } from 'node:fs/promises';

// Even if a malicious transitive dep tries this:
try {
  await readFile('/home/user/.ssh/id_rsa', 'utf-8');
} catch (e) {
  console.log(e.code);  // ERR_ACCESS_DENIED — denied by --permission
}

// The dep runs, but can't reach what isn't explicitly allowed.
// This is the modern shape of 'least privilege' for Node services.

External links

Exercise

소유한 Node 프로젝트 골라. npm audit 돌려. 모든 보고된 이슈에 대해 결정: 지금 고침 (npm audit fix), 위험 수용 + 이유 문서화, 또는 부모 의존성 업그레이드. 그 다음 CI 워크플로에 npm ci (또는 pnpm install --frozen-lockfile) 활성화. 연습 포인트는 보안을 분기별 fire drill 아닌 일상 워크플로의 일부로 만드는 거.
Hint
대부분 보고된 CVE 가 low-severity (dev-time dep, 실제로 취약 path 안 exercise 하는 transitive dep). 직접 dep 의 '프로덕션' CVE 가 행동할 거. 각자 advisory 확인: 네 코드 path 가 실제로 취약 동작 trigger 함? 안 하면 분석 문서화하고 진행. 맹목적으로 업그레이드 마 — 검증.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.