pnpm를 v10으로 업데이트한 뒤 bcrypt 모듈을 찾을 수 없다는 에러가 발생했다. 문제의 원인을 파악하는 과정에서 v10부터 Lifecycle module을 빌드시 포함하지 않는다는 것을 알게 되었다. 나는 앞으로 pnpm v10을 써야만 한다. 따라서 pnpm v10을 안정적으로 사용하기 위해 알아보고자 한다.
1️⃣ 에러가 난 이유의 핵심, v10 변경사항
2️⃣ Lifecycle module에 대한 정의
3️⃣ 바뀐 이유는?
4️⃣ Lifecycle module이 포함되게 하려면 어떻게 해야할까? 해결 방법!
pnpm v10 변경사항
[Bug]~new pnpm v10 version has conflicts with bcrypt 5.1.1 · Issue #9042 · pnpm/pnpm
Verify latest release I verified that the issue exists in the latest pnpm release pnpm version No response Which area(s) of pnpm are affected? (leave empty if unsure) No response Link to the code t...
github.com
Github에 마침 나와 똑같은 에러가 뜬 이슈가 있었다. 이슈를 보면 pnpm maintainer가 “pnpm v10부터는 종속되는 설치 스크립트를 차단합니다” 라고 말한다. 릴리즈 노트를 확인해 보니 정확하게 명시해 놓았다.
종속성의 라이프사이클 스크립트는 기본적으로 설치 중에 실행되지 않습니다. 이는 보안을 강화하기 위한 획기적인 변경입니다. 특정 종속성의 라이프사이클 스크립트를 허용하려면 package.json의 pnpm.onlyBuiltDependencies 필드에 해당 종속성을 나열해야 합니다.
차단한다는 사실은 알겠는데 왜일까? 라이프사이클 스크립트라는 것 그리고 해결방법도 정확하게 알고 싶다.
Lifecycle Script 라이프사이클 스크립트
package.json의 scripts 필드에서는 개발자가 임의로 정의한 스크립트뿐만 아니라, 미리 정해진 몇 가지 스크립트가 있다. 패키지의 생애 주기에 따라 자동으로 실행된다는 의미로 라이프 사이클 스크립트라 한다. 주로 pnpm install이나 pnpm publish 등의 명령어 실행 과정에서 자동으로 호출된다.
⚫️ preinstall (설치 직전)
⚫️ install (설치 시)
⚫️ postinstall (설치 직후)
⚫️ prepublish / postpublish (배포 전후)
pnpm은 왜 제외했을까 | 잠재된 위험성
라이프사이클 스크립트는 자동으로 실행된다는 특성 때문에 잠재적인 보안 위협이 존재한다. 사용자는 단순히 패키지를 설치하는 행위로 pnpm install만 했을 뿐인데, 내부적으로 패키지의 preinstall 또는 postinstall 스크립트가 실행되어 사용자의 데이터를 탈취하거나 악성코드를 실행할 수 있기 때문.
최근까지도 micro-username, @primeo/address, ovh-ui/oui-checkbox, node-hsf, alicov 등 이 이런 시도를 했다. pnpm 메인테이너 Zoltan Kochan은 최근 발생한 *Rspack 공급망 공격에 대한 대응으로 이런 조치를 취했다고 밝혔다. 이 공격은 @rspack/core, @rspack/cli 패키지가 설치될 때 자동으로 실행되는 postinstall 스크립트를 통해 암호화폐 “모네로”를 채굴하기 위한 XMRig 악성 코드를 배포했다.
*Rspack 공급망 공격?
Rspack은 Rust 기반의 고성능 JavaScript 번들러로, 웹팩과 유사한 기능을 제공한다. 2024년 5월 보안연구원들은 Rspack의 Github Actions 설정에서 심각한 취약점을 발견했다. 이 취약점은 외부 공격자가 악의적으로 Pull Request를 제출하여 Rspack의 npm 배포 토큰과 Github 개인 액세스 토큰(PAT)를 탈취할 수 있게 했다. 이는 개발자들의 시스템에 악성 코드를 배포하거나 CI/CD 파이프라인을 통해 생산 환경까지 영향을 미칠 수 있는 심각한 보안 위협이었다. (다행히 발견 직후 Rspack 팀에 의해 신속히 수정됐다.) 동일한 공격시도가 Vant 패키지에서도 발견되었다. 이 또한 빠른 대응으로 해결되었다.
Kochan은 사건 직후 X(트위터)에 투표를 게시하여 pnpm이 기본적으로 이러한 라이프사이클 스크립트를 차단해야 하는지에 대한 의견을 올렸다.
이런 사건이 터질 때마다 사용자들은 라이프사이클 스크립트를 실행하기 어렵게 만들어달라는 요청을 쓰나미처럼 보내옵니다. X에 올린 설문을 보면 대부분의 사용자가 기본적으로 스크립트를 차단하는 걸 찬성하고 있는 것 같습니다. 하지만 솔직히 선택의 여지가 없다고 생각해요. Bun이 이미 라이프사이클 스크립트를 기본적으로 차단하기 때문에, Bun이 pnpm보다 더 안전하다고 주장할 수 있기 때문이죠. - Kochan의 X에서 인용-
차단된 모듈 해결 방법!
pnpm build를 실행할 경우 빌드에서 무시되는 모듈을 알려준다. @nestjs/core, @scarf/scarf, bcrypt 총 세 개에 대한 경고이다. 위의 이슈 사이에서 pnpm contributor인 Cheng이 제안한 두 가지 방법 그대로 pnpm v10에 구현되었다.
approve-builds
pnpm install 진행 시 주의가 필요한 경우 검토하고 승인하는 방식. 승인할 경우 자동으로 onlyBuiltDependencies 옵션을 추가해 준다.
pnpm.onlyBuiltDependencies
미리 package.json에 권한을 허용할지 거부할지 지정해 주는 방식
pnpm v10 업데이트는 기존의 빌드 방식에 영향을 미칠 수 있다. 특히 네이티브 모듈이 정상적으로 설치되지 않는다면 나의 글을 참고하여 approve-builds와 onlyBuiltDependencies 옵션을 적용해 보길 바란다!
여러 Package manager는 보안강화를 위해 움직이고 있다. 이번 이슈를 해결하면서 보안 트렌드를 알 수 있어서 즐거웠다. 앞으로도 자주 사용하는 Docker나 pnpm의 릴리즈노트를 꼼꼼히 확인해야겠다,,,
같은 문제를 겪은 개발자들에게 도움이 되길..!
pnpm 10.0.0 Blocks Lifecycle Scripts by Default
Rspack
또 개발자들 노리는 타이포스쿼팅 공격! 이번에는 npm에서 실시돼
[nestjs] pnpm v10 업데이트 후 bcrypt 오류? 이렇게 해결하세요!
'Development Environment' 카테고리의 다른 글
수동 Docker 배포, 이젠 STOP — GitHub Actions로 자동화하기 (0) | 2025.03.30 |
---|---|
Docker Compose V2에서 .env를 못 찾는다면? (0) | 2025.03.02 |
Webpack의 Module Federation 동작 흐름 그리고 Dynamic import (0) | 2024.11.23 |
2016, Left-pad 사건에 대한 Rich Harris(Rollup)의 글로 알아보는 번들링의 중요성 (3) | 2024.08.17 |
Why Vite? JS 모듈화의 역사, CJS, ESM, Webpack (2) | 2024.08.10 |