pnpm cannot find matching keyid: {"signatures":[{"sig":"meyciqdkzyzzmbzkrcqoweefiecgp4/xv8gblxxtezz9qstrsaihapx6tvzixjtub6gpqja82vcwfhuu39jctojvcork/k39","keyid":"sha256:dhq8wr5apbvfhlf/+tc+ayvpodtpcidqohxsbhrwc7u"}]
발단
어느날 위의 메시지와 함께 도커 빌드가 실패 한다는 내용이 공유 되었습니다. 이 때 머릿속에는 여러가지 가능성이 떠올랐는데
- 변경된 코드에 문제가 있다.
- 도커 이미지에 문제가 생겼다.
- corepack 또는 pnpm 에 문제가 생겼다.
- 빌드 장비에 문제가 생겼다.
이 중 변경된 코드는 css 관련 코드라 제외 하였고 2, 3 번 중 이전에도 2번과 유사한 경험이 있어 2번을 크게 의심 하였습니다.
해결과정
해당 프로젝트는 build stage 에서 bitnami/node:22 를 사용하고 있었습니다.
원인을 찾기 위해 로컬 환경에서 재현 하였을 때 bitnami/node:22 와 node:22 모두 동일한 오류가 발생 하였기 때문에 도커 이미지의 문제가 아닌 pnpm 또는 corepack 의 문제를 의심 하였습니다.
pnpm issue 9029 corepack issue 612 를 비롯하여 여러 곳 에서 해당 문제에 대한 내용이 올라온 것 을 확인 할 수 있었으며 pnpm@10 의 출시 즈음 하여 npm 의 레지스트리 키가 rotate 되었다는 것 을 알게 되었습니다.
즉, npm 레지스트리 키가 변경 되었으며 Node.JS 에 기본으로 설치된 corepack 버전에는 새 키에 대한 정보가 없기 때문에 발생한 문제 입니다. (테스트 과정 중 알게 된 사실은 9.15.4 이상 에서도 동일한 문제가 발생하고 있습니다.)
해결 방법은 크게 3가지로 볼 수 있습니다.
COREPACK_INTEGRITY_KEYS 를 비활성화 (비추천)
COREPACK_INTEGRITY_KEYS 의 경우에는 이름 그대로 서명 확인을 비활성화 합니다. 문제는 해결 할 수 있겠지만 무결성 검증을 건너뛰게 되는 만큼 보안상 좋지 않습니다. 변조된 패키지 매니저가 설치될 수 있고 의도치 않은 동작을 할 수 있습니다.
무엇보다 기본적으로 설정된 보안을 해제하는 일은 그 누구에게도 좋은 선택이 되지는 못합니다.
COREPACK_DEFAULT_TO_LATEST 를 비활성화
이 옵션은 선택한 패키지 관리자의 최신 버전을 원격 레지스트리에서 조회하지 않도록 하며 동일한 major 버전을 다운로드할 때 Last Known Good version 를 갱신하지 않게 합니다.
오류가 발생한 프로젝트의 Dockerfile 은 아래와 같이 되어 있습니다.
RUN corepack enable pnpm
RUN pnpm install
COREPACK_DEFAULT_TO_LATEST 옵션을 비활성함으로서 변경된 키로 서명된 버전을 설치하지 않게 되어 서명 확인 실패를 해결할 수 있습니다.
FROM node:22
ENV COREPACK_DEFAULT_TO_LATEST=0
COPY ./ .
RUN corepack enable pnpm
RUN pnpm install
CMD ["pnpm", "-v"]
corepack 업데이트
문제가 되는 key 는 [email protected] 부터 포함 되었습니다. (신규 키가 추가된 커밋) 따라서 corepack 업데이트로 해당 문제를 해결할 수 있습니다.
정리
- 최근 npm registry key 가 rotate 되었다.
- pnpm 9.15.4 버전부터 신규 키 로 서명 되었다.
- corepack 은 패키지 매니저 설치 시 서명을 검증하게 되어 있다.
- corepack 0.31.0 이전 버전은 신규 npm registry key 에 대한 정보를 가지고 있지 않다.
- node:22 이미지에 설치된 corepack 은 0.30.0 이다.
- corepack 은 기본적으로 최신 버전의 패키지 매니저 설치 > package.json 의 packageManager 에 명시된 버전 설치 과정을 거친다.
- 최신 버전의 서명 키가 corepack 에 포함되어 있지 않으므로 서명 검증에 실패한다.
- 해결을 위해선 COREPACK_DEFAULT_TO_LATEST 를 비활성화 하거나 corepack 을 최신 버전으로 업데이트하면 된다.