Dependabot을 통한 안전한 의존성 관리
현대 소프트웨어 개발에서 의존성(Dependency)은 필수 불가결한 존재입니다. 직접 구현해야 하는 코드를 줄여 생산성을 높여주지만, 관리되지 않고 방치된 의존성은 보안 취약점이나 호환성 문제로 이어지기 쉽죠.
이번 글에서는 깃허브에서 제공하는 Dependabot을 통해 의존성 관리와 보안 업데이트를 어떻게 자동화할 수 있는지 알아보겠습니다.
Dependabot이란?
Dependabot은 깃허브에서 제공하는 보안 취약점 경보 및 의존성 업데이트 기능입니다. 초기에는 독립 서비스였지만, 2019년 GitHub에 인수된 후 현재는 깃허브 플랫폼에 완전히 통합되어 무료로 사용할 수 있습니다. 덕분에 Dependabot에 대한 접근성과 사용성이 크게 개선되어 복잡한 과정없이 코드 저장소에 간단한 설정만으로 바로 쓸 수 있습니다.
Dependabot은 다음 세 가지 기능으로 이루어져 있습니다.
- Alerts(알람): 코드 저장소의 보안 취약점을 감지하여 경고합니다.
- Security Updates(보안 업데이트): 보안 취약점이 발견된 의존성을 업데이트하는 Pull Request을 자등으로 생성합니다.
- Version Updates(버전 업데이트): 보안과 무관하게 의존성을 최신 상태로 유지하기 Pull Request을 자등으로 생성합니다.
npm이나 Maven, PyPI, RubyGems, Docker Hub 등과 같은 패키지 저장소를 통해 의존성을 내려받는 프로젝트는 모두 잠재적인 공급망 공격(Supply Chain Attack) 위험에 처해 있습니다. Dependabot은 점점 정교해지고 있는 공급망 공격을 방어하고, 알려진 보안 취약점으로부터 프로젝트를 지킬 수 있는 강력한 보안 도구입니다.
Dependabot 작동 원리
어떤 프로그래밍 언어의 생태계 속에서 소프트웨어 개발을 하든 의존성이 있는 프로젝트에는 패키지 설정과 잠금을 위한 파일이 존재하기 마련입니다. 그리고 이 것은 해당 프로젝트에서 어떤 패키지 매니저를 사용하느냐에 따라 결정됩니다.
예를 들어, 자바스크립트 프로젝트 package.json
, package-lock.json
, yarn.lock
, pnpm-lock.yaml
, bun.lock
과 같은 파일이 있을 것이고,
자바나 코틀린, 스칼라와 같이 JVM 계열의 언어를 사용하는 프로젝트라면 pom.xml
, build.gradle.kts
, gradle.lockfile
, 과 같은 파일이 있을 것입니다.
파이썬 프로젝트라면 requirements.txt
와 같은 파일이 있겠죠.
Dependabot은 코드 저장소에 있는 이러한 패키지 잠금 파일을 깃허브의 보안 데이터베이스와 비교하여 보안 취약점을 찾아내고, 설정에 따라 Pull Request도 자동으로 생성해줍니다. 따라서 Dependabot을 제대로 사용하려면 현재 프로젝트가 어떤 패키지 저장소로 부터 의존성을 내려받고 어떤 패키지 매니저를 쓰고 있는지 파악하고 있어야 하며, 패키지 설정 및 잠금 파일의 위치도 정확히 알고 있어야 합니다.
패키지 버전 잠금에 대한 자세한 내용은 별도의 포스팅로 다루었으니 참고 바랍니다.
Dependabot 기능 제어
Dependabot의 3가지 기능은 모두 저장소의 Settings 탭의 Advanced Security 메뉴에서 제어할 수 있습니다. 설정 페이지의 URL 형식은 다음과 같습니다.
https://github.com/<사용자 또는 조직>/<저장소>/settings/security_analysis
GitHub에서 새로운 저장소를 만들면 Alerts 기능은 일부로 비활성화 시키지 않는 이상 기본으로 활성화되어 있고요. Security Updates와 Version Updates는 직접 활성화를 해줘야 합니다. Version Updates의 경우 별도의 설정 파일도 필요한데, 이 부분에 대해서는 아래에서 다루겠습니다.
Alerts 기능
단순히 코드 저장소에 존재하는 보안 취약점에 대해서 경보를 받고 싶다면 Dependabot의 Alerts 기능을 사용합니다. 보안 취약점은 Security 탭의 Dependabot 메뉴를 통해서 확인할 수 있습니다. 보안 경고 페이지의 URL 형식은 다음과 같습니다.
https://github.com/<사용자 또는 조직>/<저장소>/demo/security/dependabot
목록 페이지에서는 현재 코드 저장소에 어떤 보안 취약점이 있고 과거에 어떤 보안 취약점을 조치했는지 알 수 있습니다. 뿐만 아니라 패키지 이름, 생태계, 패키지 관리자 파일, 심각도 별로 필터링 및 정렬도 지원해서 보안 취약점이 많은 경우에도 파악이 용이합니다.
경고 하나를 클릭하여 상세 페이지로 들어가면 해당 보안 취약점에 대한 CVE 또는 GHSA에 참조를 포함한 아주 자세한 정보를 확인해볼 수 있습니다. 어떤 이유로든 보안 취약점을 조치할 수 없는 상황이라면 이유를 선택하고 해당 경보를 해제할 수도 있습니다.
바로 다음에 다룰 Security Updates 기능이 활성화되어 있다면 여기서 바로 Pull Request를 생성할 수 있습니다.
Security Updates 기능
보안 경고를 받더라도 어떤 패키지를 어떻게 업데이트해야 할지 보안 전문가가 아니라면 모를 때가 많습니다. 이때 유용한 것이 바로 Dependabot의 Security Updates 기능인데요. 이 기능을 켜놓으면 Dependabot이 알아서 어떤 패키지를 어떤 버전으로 업데이트해야하는지 파악하여 PR을 생성해줍니다.
너무 당연한 얘기이겠지만 보안 위험을 최소화하기 위해서 Security Updates를 통해서 생성된 Pull Request는 가능한 신속하게 검토하고 병합하는 것이 권장됩니다.
Version Updates 기능
Version Updates 기능은 보안과 관계없이 프로젝트이 모든 의존성을 지속적으로 최신 상태로 유지하기 위한 기능입니다.
Dependabot의 다른 기능과 달리 Version Updates을 활성화하려면 별도의 설정 파일을 필요한데요.
코드 저장소의 .github
디렉토리 안에 dependabot.yml
파일을 생성해야 합니다.
예를 들어, 패키지 매니저로 npm을 사용하는 React 프로젝트의 경우 다음과 같이 설정을 할 수 있습니다.
- 매일 업데이트를 하며, Pull Request에는
deps
태그를 답니다. - React 관련 패키지는 묶어서 하나의 Pull Request로 올립니다.
- Testing Library 관련 패키지는 자동으로 업데이트하지 않습니다.
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
labels:
- "deps"
react:
patterns:
- "react"
- "react-dom"
- "@types/react*"
update-types:
- "minor"
- "patch"
ignore:
- dependency-name: "@testing-library*"
Dependabot은 하나의 코드 저장소에서 여러 생태계를 동시에 지원하기 때문에 모노리포(monorepo)에서도 사용하는데 문제가 없습니다.
예를 들어서, 자바스크립트와 루비를 동시에 사용하는 프로젝트에서는 다음과 같이 업데이트 주기를 다르게 설정할 수 있습니다.
version: 2
updates:
- package-ecosystem: npm
directory: "/javascript"
schedule:
interval: "weekly"
- package-ecosystem: bundler
directory: "/ruby"
schedule:
interval: "monthly"
그 밖에 어떤 설정이 가능한지는 공식 레퍼런스 문서를 참고바랍니다.
dependabot.yml
파일을 생성하고 Version Updates 기능을 활성화하면 설정해놓은 스케줄에 따라서 코드 저장소에 자동으로 Pull Request가 올라오게 됩니다.
Dependabot이 생성해준 Pull Request는 저장소의 기본 브랜치에 맞춰서 자동으로 업데이트가 되서 매우 편리합니다.
주의 사항
Security Updates나 Version Updates을 통해서 자동으로 생성된 Pull Request가 병합했을 때 소프트웨어가 정상적으로 작동할지는 Dependabot이 보장하지 않습니다. 그러므로 반드시 개발자가 새로운 버전과 호환성 문제가 없는지를 확인하고 깨지는 부분에 대해서 적절한 조치를 취한 후에 Pull Request를 병합해야 합니다. 특히 major나 minor 버전이 업데이트될 때는 위험이 더 크므로 각별히 주의가 필요합니다.
Dependabot이 자동으로 생성해준 Pull Request을 사람이 임의로 건드리면 Dependabot은 해당 PR을 더 이상 자동으로 관리해주지 않습니다.
따라서 가급적 @dependabot rebase
나 @dependabot recreate
와 같은 코멘트를 PR에 달아서 Dependabot에게 원하시는 작업을 명령하는 방식으로 사용해주세요.
마치며
지금까지 깃허브에서 제공하는 Dependabot을 통해서 어떻게 보안 취약점 관리하고 의존성 업데이트를 자동화할 수 있는지 알아보았습니다. Dependabot를 잘 활용하셔서 최소한의 노력으로 여러분의 프로젝트를 보안 취약점으로 부터 보호하고 항상 패키지를 최신 상태로 유지하실 수 있으셨으면 좋겠습니다.