콤퓨타이슈 npm 배포 정책 변경, 소프트웨어 공급망 보안 강화
신규 패키지 공개 전 승인과 미검증 신뢰 설정 만료, 최근 배포 사고로 본 검증의 중요성
페이지 정보
본문
작성일

홈페이지를 만드는 코드는 모두 한 회사에서 작성되지 않는다. 화면을 구성하는 라이브러리, 파일을 변환하는 도구, 빌드와 배포를 수행하는 자동화까지 여러 개발자가 만든 코드를 가져와 사용한다. 따라서 서비스의 신뢰를 살펴보려면 직접 작성한 코드와 함께 외부 코드가 들어오는 경로도 확인해야 한다.
최근 npm의 업데이트는 이 경로에서 누가 파일을 제출할 수 있고, 누가 공개를 승인하며, 어떤 자동화 실행에 배포 권한을 줄 것인가를 더 세밀하게 나누고 있다. GitHub는 9월 18일 단계적 배포 전용 토큰을 발표했고, 10월 2일에는 신규 패키지의 승인 대기 생성과 미검증 배포 신뢰 설정의 만료 정책을 공개했다.[1][2][3]
10월 5일에는 보안업체 StepSecurity가 npm 패키지 @subql/common@5.8.3의 악성 동작을 보고했다. 이 사건은 배포 인증의 강화와 함께 실제 배포 파일을 검토해야 하는 이유를 보여준다. 두 npm 정책이 이 사건 때문에 도입됐다는 인과관계는 확인되지 않았다.[5][6]
1. 소프트웨어 공급망은 설치 버튼 앞에서 시작된다
소프트웨어 공급망(Software Supply Chain)은 소스 코드가 작성되고, 빌드되고, 배포되어 다른 서비스에서 사용되는 경로를 뜻한다. 여기에는 개발자와 소스 저장소뿐 아니라 빌드 환경, 배포 파일, 패키지 저장소와 의존성도 포함된다. 공급망 보안의 핵심은 이 연결 과정에서 의도하지 않은 변경이나 파일 교체가 들어오는 지점을 확인하는 것이다.[7]
자바스크립트 생태계에서 널리 쓰이는 npm은 개발자가 패키지를 공유하고 프로젝트에 설치할 수 있도록 한다. 패키지는 재사용할 코드와 관련 정보를 묶은 단위다. 다른 패키지가 필요한 경우에는 추가 의존성도 함께 해결된다. 그래서 프로젝트가 직접 선택한 이름 몇 개만으로 설치되는 코드 전체를 설명할 수는 없다.[8]
이때 저장소의 소스 코드와 사용자가 설치하는 배포물(Artifact)을 구분해야 한다. 빌드가 소스를 변환하거나 생성 파일을 추가할 수 있고, 배포 과정에서도 파일을 다룬다. SLSA의 공급망 모델 역시 소스가 의도대로 관리되는지와 최종 패키지가 올바른 입력·절차로 만들어지는지를 나누어 설명한다.[7]
최근 발표를 읽는 기준
배포 권한은 ‘누가 올릴 수 있는가’를, 승인 절차는 ‘언제 공개할 것인가’를, 출처 증명은 ‘어떤 경로가 기록됐는가’를 확인한다. 각 단계의 확인 결과를 코드의 안전성 전체로 확대해서 읽지 않아야 한다.

2. 신규 npm 패키지도 공개 전에 검토할 수 있게 됐다
GitHub의 10월 2일 발표에 따르면, 이제 npm stage publish로 새로운 패키지를 생성할 수 있다. 로컬 세션이나 세분화 접근 토큰(Granular Access Token)을 사용할 수 있으며, 단계적 배포 전용 토큰도 포함된다. 자동화 작업에서 신규 패키지를 만들 때 먼저 수동으로 첫 배포를 해야 하는 부담을 줄이는 변화다.[2]
단계적 배포(Staged Publishing)는 파일을 곧바로 공개하는 대신 검토 대기 영역에 제출하는 방식이다. 패키지 관리자가 검토하고 2단계 인증(Two-factor Authentication, 2FA)을 거쳐 승인하면 해당 버전이 공개된다. npm 문서는 제출된 압축 파일을 내려받아 살펴볼 수 있는 절차도 제공한다.[4]
| 단계 | 하는 일 | 확인할 대상 |
|---|---|---|
| 제출 | 자동화 또는 개발자가 버전을 검토 대기 영역에 올린다. | 제출 권한과 대상 패키지 |
| 검토 | 관리자가 제출된 버전과 파일을 살펴본다. | 공개하려는 실제 배포물 |
| 승인 | 관리자가 2단계 인증으로 공개를 승인한다. | 공개 결정과 승인자 |
이번 확대는 공개 패키지의 scoped·unscoped 유형과 비공개 scoped 패키지를 지원한다. scoped는 @조직/패키지처럼 이름에 범위를 붙이는 형식이다. 실제 첫 버전은 관리자가 승격해야 설치 가능해지고, 패키지를 생성한 뒤 설정과 신뢰 기반 배포를 구성할 수 있다.[2]
신규 생성 때는 공개된 자리표시 버전 0.0.0-stage가 생길 수 있다. 따라서 승인 전까지 패키지 이름조차 드러나지 않는 구조로 이해하면 안 된다. 공개된 자리표시 버전과 아직 승인되지 않은 실제 버전의 내용을 구분해야 한다. 공식 문서의 최소 요구사항은 npm CLI 11.15.0과 Node.js 22.14.0이다.[4]
여기서 주목할 변화는 자동화의 제출과 사람의 공개 결정을 분리할 수 있다는 점이다. 모든 npm 패키지에 이 절차가 강제되는 것은 아니며, 승인 기능을 사용한다고 해서 사람이 모든 코드를 검토했다는 의미도 아니다.
3. stage-only 토큰은 무엇을 제한하는가
이 흐름은 9월 18일 발표된 단계적 배포 전용 토큰(Stage-only Token)과 연결된다. 해당 토큰은 자동화가 검토용 버전을 제출할 수 있도록 하면서, 새로운 버전을 직접 공개하는 npm publish는 거부한다. 자동화를 위해 2단계 인증을 우회하도록 설정했더라도 직접 배포 제한은 유지된다.[1]
다만 이름만 보고 읽기 전용 수준의 권한이라고 생각하면 안 된다. GitHub는 이 토큰에 배포 태그를 이동하거나 버전의 사용 중단을 표시하는 등의 다른 쓰기 권한이 남아 있다고 설명한다. 직접 공개가 제한됐다는 사실과 패키지 운영에 영향을 줄 수 없다는 주장은 다르다.[1]
9월 발표는 선택적으로 적용하는 기능이며 기존 토큰의 직접 배포 능력을 자동으로 바꾸지 않는다. 또한 GitHub는 2단계 인증을 우회하는 토큰을 통한 직접 배포 제거 목표를 2027년 1월로 안내했다. 이는 발표에 명시된 향후 목표로, 현재 모든 토큰 배포가 중단됐다는 뜻은 아니다.[1]
4. ‘48시간 만료’는 미검증 신뢰 설정에 적용된다
신뢰 기반 배포(Trusted Publishing)는 개방형 인증 연결(OpenID Connect, OIDC)을 사용해 승인된 자동화 실행의 정체성을 확인하는 방식이다. 패키지에 특정 저장소와 워크플로 등을 등록하고, 해당 실행에서 단기 자격 증명을 사용해 배포한다. 장기 npm 쓰기 토큰을 자동화 환경에 보관하는 부담을 줄일 수 있다.[9]
GitHub는 10월 2일부터 검증되지 않은 신뢰 기반 배포 설정이 생성 48시간 후 만료되며, 더 이상 배포를 허용하지 않는다고 발표했다. 저장소나 프로젝트 이름의 소유권이 바뀔 때 남아 있는 신뢰 설정의 위험을 제한하기 위한 조치다.[3]
| 설정 상태 | 발표에서 설명한 동작 |
|---|---|
| 새로 생성됐지만 성공 배포로 검증되지 않음 | 생성 48시간 후 배포 권한이 만료된다. |
| 첫 성공 배포로 검증됨 | 미검증 설정 만료 대상에서 제외된다. |
| 저장소·프로젝트 정체성이 변경됨 | 새 신뢰 관계와 48시간 검증 기간이 필요하다. |
| 만료됨 | 설정은 남지만 배포를 허용하지 않는다. 재생성할 수 있다. |
일반적인 설정 수정은 만료 기한을 다시 시작하지 않는다. 패키지에 있는 다른 유효한 설정도 영향을 받지 않는다. 같은 발표에서는 GitHub Actions의 issue_comment 이벤트에서 오는 배포 토큰도 거부한다고 안내했다. 이는 기존 pull_request_target 제한에 추가된 것으로, 댓글 기반 이벤트를 배포 경로로 사용하는 자동화는 실행 이벤트를 검토해야 한다.[3]
이 변경은 패키지 버전이 48시간 뒤 사라진다는 정책이 아니다. ‘검증되지 않은 배포 신뢰 관계’를 정리하는 규칙이다. 저장소 이름을 등록하는 단계와 실제 배포가 성공해 해당 관계가 검증되는 단계를 구분하면 적용 범위를 이해하기 쉽다.

5. 10월 5일 보고는 실제 배포 파일의 문제를 드러냈다
StepSecurity는 10월 5일 @subql/common@5.8.3을 분석해 자격 증명을 수집하고 원격 셸 접근을 지원하는 숨겨진 코드를 확인했다고 보고했다. 조사 대상은 SubQuery 생태계의 공통 라이브러리다. 보고서는 개발자 작업 환경과 지속적 통합(CI) 환경을 대상으로 하는 동작을 설명한다.[5]
조사에서 중요한 지점은 파일의 실행 시점과 배포 직전의 교체다. 보고서에 따르면 악성 동작은 설치 스크립트와 코드 가져오기(import)에서 각각 시작할 수 있었다. 또한 저장소 소스를 빌드한 뒤 외부 아카이브로 패키지 디렉터리를 바꾸는 워크플로 변경이 발견됐다. 추가된 교체 단계에는 외부 파일의 해시나 서명을 검증하는 절차가 없었다고 설명한다.[5]
StepSecurity 측이 작성한 공개 이슈 #3047은 해당 버전이 GitHub Actions OIDC 신뢰 기반 배포를 통해 게시됐다고 보고한다. 이슈는 프로젝트 저장소에 올라온 조사자의 신고이며, 프로젝트 관리자가 발행한 공식 사고 확정 공지와 구분해야 한다. 10월 6일 확인한 이슈 화면에서는 관리자의 답변을 확인하지 못했다.[6]
따라서 공격자의 신원이나 최초 침입 경로, 전체 피해 규모를 이번 자료만으로 확정할 수는 없다. 해당 조사 보고와 공개 이슈는 같은 조사기관의 자료다. 두 개의 독립적인 조사 결과로 세거나, 저장소에 표시된 계정명을 실제 공격자의 신원으로 단정해서는 안 된다.
이 사례에서 확인할 수 있는 질문은 명확하다. 승인된 배포 정체성으로 파일이 올라왔더라도, 그 파일을 만드는 과정과 최종 내용은 따로 살펴봐야 한다. 설치 스크립트 차단만으로 이후 import 경로까지 통제했다고 볼 수도 없다.
6. 출처 증명이 있다는 것은 무엇을 의미하는가
배포 출처 증명(Provenance)은 패키지의 소스와 빌드 지침 등에 연결되는 검증 가능한 정보를 제공한다. npm은 출처 증명과 권한 있는 사용자의 게시를 레지스트리가 기록하는 배포 증명을 구분한다. 서명과 공개 투명성 기록은 이러한 정보의 진위와 변경 여부를 확인하는 데 사용된다.[10]
npm 공식 문서는 출처 증명이 있는 패키지라도 악성 코드가 없다고 보장하지 않는다고 명시한다. 증명은 개발자가 경로를 확인하고 검토할 수 있는 근거다. 기록의 존재와 코드에 대한 안전성 판단은 별도의 단계로 남는다.[10]
| 기능 | 직접 다루는 질문 | 추가로 살펴볼 부분 |
|---|---|---|
| 신뢰 기반 배포 | 승인된 자동화 실행이 배포하는가? | 그 실행의 권한과 실제 동작 |
| 단계적 배포 | 공개 전에 관리자가 승인하는가? | 승인 대상 파일과 검토 내용 |
| 출처 증명 | 어떤 소스·빌드 경로와 연결되는가? | 기대하는 경로인지, 코드의 동작이 적절한지 |
이 표의 ‘추가로 살펴볼 부분’은 공식 문서의 기능 범위를 바탕으로 정리한 해석이다. 각각의 확인을 연결하면 기록을 통해 판단할 수 있는 범위가 넓어지지만, 하나의 배지나 인증 결과를 모든 보안 검토의 대체물로 사용할 수는 없다.
7. 홈페이지 유지보수에서는 무엇이 달라지는가
직접 npm 패키지를 배포하지 않는 회사도 외부 패키지를 소비하는 입장에서 이 변화를 읽을 수 있다. 공급자에게는 제출·승인·배포 권한을 나누는 문제가 있고, 소비자에게는 어떤 버전과 파일을 채택했는지 확인하는 문제가 있다. 아래는 최근 발표와 공식 문서에서 도출한 실무 관점이다.
사용한 전체 의존성 트리를 기록한다
잠금 파일(Lockfile)인 package-lock.json은 해결된 의존성 트리를 기록한다. npm 문서는 이를 저장소에 포함해 팀원과 배포 환경이 같은 의존성을 설치하고, 변경 차이를 확인하도록 설명한다. 상위 패키지의 이름과 버전만 기록하는 것보다 실제 채택한 구성을 추적하기에 적합하다. 다만 잠긴 버전 자체가 안전하다는 인증서는 아니다.[8]
인증 성공과 취약점 검사 결과를 따로 읽는다
npm audit는 알려진 취약점에 관한 보고를 요청한다. npm audit signatures는 레지스트리 서명과 출처 증명을 검증한다. 검사 이름이 비슷하더라도 확인하는 대상은 다르다. 어느 검사를 수행했고 무엇을 확인했는지 기록해야 ‘검사 통과’라는 한 문장보다 결과를 정확하게 설명할 수 있다.[11]
배포 파일을 만드는 자동화도 검토한다
GitHub는 자동화 토큰에 최소 권한을 부여하고 외부 action을 전체 커밋 식별자로 고정하는 등의 보안 원칙을 안내한다. 기능 코드가 바뀌지 않더라도 자동화 설정이 달라지면 실행되는 코드와 파일 처리 경로가 달라질 수 있다. 워크플로 변경은 최종 결과물에 영향을 주는 변경으로 읽어야 한다.[12]
사고 패키지와 고객 서비스를 연결할 자료를 남긴다
소프트웨어 구성요소 목록(Software Bill of Materials, SBOM)은 프로젝트의 구성요소를 정리하는 자료다. npm은 SPDX와 CycloneDX 형식의 목록 생성을 지원한다. 다만 잠금 파일만 읽어 만든 목록과 실제 설치·배포 상태는 구분해야 한다. 기록의 대상과 생성 시점을 함께 남겨야 특정 버전이 어느 서비스에 포함됐는지 판단하는 데 도움이 된다.[13]
8. 최근 변화가 넓히는 확인의 범위
이번 발표들을 함께 읽으면 npm이 배포 권한을 더 세분화하고 있다는 흐름이 보인다. 자동화에는 제출 권한을 주고, 공개 결정에는 사람의 승인을 둘 수 있으며, 검증되지 않은 배포 신뢰 관계에는 유효 기간을 적용한다. 이는 각 발표를 연결한 해석이다.
동시에 최근 사고 보고는 승인된 배포 경로와 실제 배포 파일을 함께 확인해야 하는 이유를 보여준다. 저장소에 무엇이 있었는지, 빌드가 무엇을 했는지, 공개된 패키지에 무엇이 들어갔는지는 연결해서 살펴볼 대상이다.
소프트웨어 공급망의 신뢰는 어떤 코드를 선택했는지에 더해, 어떤 경로로 받아들였고 무엇을 확인했는지 설명할 수 있는 기록에서 구체화된다. 최근 npm의 변화는 그 기록과 권한을 나누는 도구를 늘리고 있다. 실제 안전성 판단에는 각 도구가 확인해주는 범위와 남아 있는 검토 대상을 함께 읽는 일이 필요하다.
용어 정리
| 용어 | 뜻 |
|---|---|
| 소프트웨어 공급망 | 소스 작성부터 빌드·배포·설치·사용까지 연결되는 경로 |
| 배포물 | 사용자에게 전달되는 패키지나 생성 파일 등의 결과물 |
| 단계적 배포 | 공개 전에 파일을 제출하고 관리자의 검토·승인을 거치는 방식 |
| 신뢰 기반 배포 | 승인된 자동화 실행의 정체성을 인증해 배포하는 방식 |
| 배포 출처 증명 | 소스·빌드 지침과 패키지를 연결하는 검증 가능한 정보 |
| 의존성 | 프로젝트나 다른 패키지가 필요로 하는 외부 코드 |
| 잠금 파일 | 해결된 의존성 트리와 버전 등의 정보를 기록한 파일 |
| 소프트웨어 구성요소 목록 | 구성요소와 관계를 정리해 분석·추적에 사용하는 자료 |
참고 자료
발표일과 조사 보고일을 구분했다. 제품 동작은 2026년 10월 6일 조회한 공식 문서를 기준으로 정리했으며, 사건 내용은 조사기관에 귀속했다.
- GitHub · Stage-only npm tokens for safer automation — 2026.09.18.
- GitHub · npm staged publishing now supports creating new packages — 2026.10.02.
- GitHub · Unvalidated npm trusted publishing configurations now expire — 2026.10.02.
- npm Docs · Staged publishing for npm packages
- StepSecurity · SubQuery Ecosystem Compromise: Hidden Credential Theft and Backdoors — 2026.10.05.
- subquery/subql · 공개 이슈 #3047, StepSecurity 측 신고 — 2026.10.05.
- SLSA 1.2 · Supply chain threats
- npm Docs · package-lock.json, CLI v12
- npm Docs · Trusted publishing for npm packages
- npm Docs · Generating provenance statements
- npm Docs · npm audit, CLI v12
- GitHub Docs · Secure use reference
- npm Docs · npm sbom, CLI v12
- 이전글소프트웨어 공급망 보안: SBOM·서명·출처 증명의 차이 26.10.06
- 다음글음성 AI는 어떻게 기기를 제어할까? 음성 인식부터 도구 호출까지 26.10.02
