Dependabot이 새 패키지를 3일 기다린다: 공급망 보안을 ‘업데이트 속도’가 아니라 정책으로 운영하는 법

개발

어제 공개된 패키지를 오늘 자동 병합하는 것이 항상 ‘빠른 유지보수’는 아니다. 새 버전이 깨졌거나, 게시 계정이 탈취됐거나, 악성 코드가 뒤늦게 발견되는 경우라면 업데이트 자동화가 공격자의 배포망이 될 수 있다. GitHub는 7월 14일부터 Dependabot의 일반 버전 업데이트가 레지스트리에 공개된 지 최소 3일이 지난 릴리스만 PR로 만들도록 기본값을 바꿨다. 중요한 변화지만, 이 3일을 보안 인증서처럼 믿으면 안 된다. cooldown은 패키지를 무해하게 만드는 검증이 아니라 팀이 판단할 시간을 확보하는 ‘관찰 창’이다.

패키지 공개 후 Dependabot의 3일 관찰 창, 업데이트 PR, dependency review, 고정 설치와 배포를 연결하고 보안 업데이트는 즉시 우회하는 공급망 정책 다이어그램
3일 cooldown은 PR 생성 전 관찰 창이다. 실제 방어선은 검토, lockfile, 설치 정책, CI와 긴급 예외 절차가 이어질 때 완성된다.

무엇이 바뀌었나: 기본값이 ‘즉시’에서 ‘최소 3일 후’로

GitHub의 공식 변경 사항은 Dependabot version updates에 적용된다. 새 릴리스가 레지스트리에 공개된 지 최소 3일이 지나기 전에는 버전 업데이트 PR을 열지 않는다. github.com의 모든 지원 생태계에 기본 적용되며, GitHub Enterprise Server에는 3.23부터 반영될 예정이다. 별도 설정이 없어도 동작한다.

반대로 알려진 취약점을 고치는 security updates는 기다리지 않는다. GitHub는 보안 업데이트 PR을 즉시 열어 critical fix가 cooldown 때문에 늦어지지 않도록 분리했다. 일반 최신 버전을 따라가는 일과 이미 알려진 취약점을 제거하는 일은 같은 자동화 화면에 있어도 서로 다른 위험 시간표를 가진다는 뜻이다.

팀은 .github/dependabot.ymlcooldown으로 기본값을 덮어쓸 수 있다. 공식 옵션은 default-days와 SemVer major·minor·patch별 일수, include, exclude를 제공한다. 일수는 1~90일, include와 exclude는 각각 최대 150개 항목을 받을 수 있으며 exclude가 우선한다. 다만 새 기본 3일이 모든 저장소에 최적이라는 뜻은 아니다.

3일은 검증 기간이 아니라 신호가 쌓일 시간이다

cooldown의 가치는 ‘3일이 지나면 안전하다’가 아니다. 문제가 있는 릴리스가 철회되거나, maintainer와 사용자 이슈가 쌓이거나, 보안 경고가 공개될 기회를 조금 더 확보하는 데 있다. 반대로 조용한 3일은 무해함의 증거가 아니다. 사용자가 적은 패키지, 표적 공격, 지연 실행형 악성 코드라면 신호가 늦거나 전혀 나타나지 않을 수 있다.

또한 cooldown과 Dependabot schedule은 서로 다른 시계다. 매주 화요일에만 확인하는 저장소라면 3일을 지난 직후가 아니라 다음 예약 실행 때 PR이 생긴다. PR이 열린 뒤 리뷰 대기, CI, 배포 창까지 더하면 릴리스 공개와 프로덕션 반영 사이의 실제 시간은 3일보다 길 수 있다. 팀은 숫자 하나보다 ‘release → bot check → PR → merge → deploy’ 전체 lead time을 봐야 한다.

따라서 patch는 짧게, major는 길게 기다리는 정책도 가능하지만 SemVer를 위험 등급과 동일시해서는 안 된다. patch에도 공급망 공격이 들어갈 수 있고, major가 긴급 호환성 문제를 해결할 수도 있다. 버전 크기는 정책 입력 중 하나일 뿐, maintainer 신뢰, 실행 권한, 배포 영향, 롤백 가능성과 함께 판단해야 한다.

가장 중요한 경계: Dependabot PR과 실제 설치는 다르다

Dependabot cooldown은 버전 업데이트 PR을 언제 만들지 제어한다. 개발자가 터미널에서 npm install package@latest를 실행하거나, lockfile 없는 CI가 범위 지정 의존성을 다시 해석하거나, 다른 자동화가 업데이트를 만들면 이 정책을 자동으로 통과하지 않는다. ‘Dependabot이 3일 기다린다’와 ‘우리 조직은 3일 미만 패키지를 설치할 수 없다’는 전혀 다른 문장이다.

npm은 최신 CLI에서 min-release-age라는 설치 계층 필터를 제공한다. 예를 들어 프로젝트 .npmrcmin-release-age=3을 두면 npm이 기준보다 새 릴리스를 dependency tree에 선택하지 않도록 할 수 있다. 내부 패키지처럼 즉시 받아야 하는 이름은 min-release-age-exclude로 예외 처리할 수 있다. 이것은 npm에 관한 공식 기능이며 다른 package manager에는 각자의 지원 여부와 문법을 확인해야 한다.

이미 승인된 tree를 재현하는 배포에는 lockfile과 npm ci가 중요하다. npm 문서상 npm ci는 package.json과 lockfile이 맞지 않으면 실패하고, lockfile을 다시 쓰지 않는다. 즉 업데이트 PR에서 생성·검토한 정확한 tree가 CI와 배포로 이어지는 경계를 만든다. cooldown은 새 tree가 만들어지는 시점을 늦추고, frozen install은 승인 없이 tree가 바뀌는 것을 막는다.

PR이 열렸다면 ‘나이’보다 변경된 트리를 검토하라

3일을 기다린 PR도 자동 병합 전에 dependency diff를 봐야 한다. GitHub Dependency Review는 manifest와 lockfile의 변경에서 direct·transitive dependency, 릴리스 날짜, 알려진 취약점 등을 보여준다. Dependency Review Action을 required check로 두면 설정한 취약점이나 라이선스 기준을 위반하는 변경을 merge gate에서 막을 수 있다.

실무에서는 단위 테스트 통과만으로 충분하지 않다. 새 lifecycle script가 생겼는지, native binary나 network access가 추가됐는지, lockfile에서 예상보다 많은 transitive package가 바뀌었는지, maintainer·registry·artifact 출처가 달라졌는지 확인해야 한다. 위험한 패키지는 sandbox나 네트워크 제한 환경에서 install·build 동작을 별도로 관찰할 수 있다.

자동 병합 정책도 dependency class에 맞춰 나눈다. 타입 정의나 lint rule과 production runtime dependency는 피해 반경이 다르고, GitHub Actions나 container base image는 빌드 권한에 직접 닿는다. ‘patch + CI green’ 하나로 모든 생태계를 자동 승인하기보다 실행 권한과 프로덕션 도달 범위에 따라 reviewer와 gate를 다르게 두는 편이 안전하다.

커뮤니티 신호: 사람들이 묻는 것은 ‘3일이면 충분한가’보다 ‘어디까지 적용되나’다

개발자 커뮤니티의 minimum release age 논의에서는 direct dependency PR만 늦추면 transitive dependency가 다른 설치 경로로 들어오는 문제를 막지 못한다는 우려가 반복된다. 또 Dependabot 알림과 PR이 너무 많아 자동화를 꺼버렸다는 피로도 신호도 보인다. 이 게시물들은 공식 동작을 증명하는 근거가 아니라, 팀이 설명해야 할 혼동 지점을 보여주는 audience signal로만 봐야 한다.

첫 번째 혼동은 앞서 본 PR 계층과 install 계층의 차이다. 두 번째는 version update와 security update가 분리된다는 사실이다. 세 번째는 cooldown이 PR 수를 반드시 줄이는 기능은 아니라는 점이다. 업데이트를 묶는 groups, 실행 주기, open-pull-requests limit, reviewer capacity까지 함께 설계해야 실제 피로가 줄어든다.

좋은 운영 정책은 ‘느리게 업데이트하자’가 아니다. 보안 패치는 빠르게, 일반 업데이트는 충분한 관찰과 검토를 거쳐, 긴급 예외는 기록과 만료가 있는 방식으로 처리하는 것이다. 속도를 하나로 고정하는 대신 위험 종류별로 다른 차선을 만드는 접근이다.

오늘 적용할 실무 체크리스트

1. 조직의 모든 dependabot.yml을 검색해 cooldown을 명시한 저장소와 새 기본값을 따르는 저장소를 구분한다.

2. version update와 security update의 SLA를 따로 문서화하고, 보안 업데이트가 즉시 생성된다는 사실을 담당자에게 설명한다.

3. production dependency, dev tool, GitHub Actions, container, IaC provider별로 관찰 일수와 reviewer를 정한다.

4. 아래 예시처럼 major·minor·patch를 다르게 시작하되, 팀의 배포 속도와 실제 incident 데이터를 보고 조정한다.

5. 내부 패키지나 긴급 호환성 패키지는 exclude 후보로 관리하고, 예외 owner·사유·만료일을 남긴다.

6. Dependency Review Action을 merge gate로 연결하고 lockfile의 transitive 변경까지 검토한다.

7. Node/npm 프로젝트는 현재 CLI에서 min-release-age 지원을 확인한 뒤 프로젝트 .npmrc로 install-time 정책을 검토한다.

8. CI와 production build는 lockfile을 commit하고 npm ci 같은 frozen install을 사용한다.

9. 긴급 업데이트에는 cooldown을 우회할 수 있는 승인 절차와 rollback·canary 계획을 함께 둔다.

10. PR 생성 지연, merge lead time, 실패·rollback, 알려진 취약점 노출 시간을 측정해 숫자를 재조정한다.

리스크와 반론

‘항상 최신이 가장 안전하다’는 주장은 알려진 취약점 수정에는 강한 근거가 있지만, 모든 일반 릴리스에 그대로 적용되지는 않는다. GitHub가 security update를 cooldown에서 제외한 이유도 이 두 흐름을 분리하기 위해서다. 반대로 ‘무조건 오래 기다리면 안전하다’ 역시 틀리다. 오래된 버전에는 이미 알려진 취약점과 호환성 부채가 쌓일 수 있다.

3일 대기가 작은 팀의 업데이트 처리량을 낮추지는 않을 수 있다. PR이 늦게 열릴 뿐 결국 같은 수가 올 수도 있다. 이 문제는 grouping과 일정, 자동 병합 범위, reviewer capacity로 풀어야 한다. cooldown을 PR 피로도 기능으로만 도입하면 기대와 결과가 어긋날 수 있다.

마지막으로 install-time age gate도 만능은 아니다. 사내 registry의 timestamp 정확성, 이미 lockfile에 들어온 버전, Git·URL dependency, 예외 목록을 별도로 살펴야 한다. 좋은 공급망 보안은 한 설정이 아니라 release age, provenance, dependency diff, 테스트, 최소 권한, 재현 가능한 설치와 빠른 회전을 겹쳐 놓는 일이다.

정답이 아니라 시작점으로 쓰는 정책 예시

version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "daily"
    cooldown:
      default-days: 7
      semver-major-days: 30
      semver-minor-days: 7
      semver-patch-days: 3
      exclude:
        - "@myorg/*"

이 숫자는 GitHub의 권장값이 아니라 팀 토론을 위한 예시다. 실제 위험, 업데이트 주기와 긴급 예외를 기준으로 조정한다.

Dependabot cooldown 운영 체크포인트

1. 조직의 모든 dependabot.yml을 검색해 cooldown을 명시한 저장소와 새 기본값을 따르는 저장소를 구분한다.

2. version update와 security update의 SLA를 따로 문서화하고, 보안 업데이트가 즉시 생성된다는 사실을 담당자에게 설명한다.

3. production dependency, dev tool, GitHub Actions, container, IaC provider별로 관찰 일수와 reviewer를 정한다.

4. 아래 예시처럼 major·minor·patch를 다르게 시작하되, 팀의 배포 속도와 실제 incident 데이터를 보고 조정한다.

5. 내부 패키지나 긴급 호환성 패키지는 exclude 후보로 관리하고, 예외 owner·사유·만료일을 남긴다.

6. Dependency Review Action을 merge gate로 연결하고 lockfile의 transitive 변경까지 검토한다.

7. Node/npm 프로젝트는 현재 CLI에서 min-release-age 지원을 확인한 뒤 프로젝트 .npmrc로 install-time 정책을 검토한다.

8. CI와 production build는 lockfile을 commit하고 npm ci 같은 frozen install을 사용한다.

9. 긴급 업데이트에는 cooldown을 우회할 수 있는 승인 절차와 rollback·canary 계획을 함께 둔다.

10. PR 생성 지연, merge lead time, 실패·rollback, 알려진 취약점 노출 시간을 측정해 숫자를 재조정한다.

공식 변경 사항: GitHub Changelog: Dependabot version updates introduce default package cooldown

정리

Dependabot의 기본 3일 cooldown은 자동 업데이트의 속도를 조금 늦추는 변경이지만, 더 큰 의미는 업데이트를 ‘최신 버전 추적’이 아니라 위험별 시간 정책으로 다루게 만든다는 데 있다. 보안 업데이트는 즉시, 일반 업데이트는 관찰 후, 설치는 lockfile과 resolver 정책으로 고정하고, 예외에는 owner와 만료를 붙여야 한다.

출처

다른 글