2026년 하루 평균 보고된 CVE가 전년 대비 131% 증가했습니다.

종속성

전이적 종속성이란 무엇입니까?

전이적 종속성은 다른 패키지가 필요로 하기 때문에 소프트웨어가 사용하게 되는 패키지입니다. 직접 선언한 적은 없지만 출시하는 제품에 포함되며, 자체 취약점과 라이선스를 가지고 있습니다. 전이적 종속성을 확인하고, 수정하고, 각 릴리스에 어떤 것이 들어갔는지 입증하는 방법을 소개합니다.

업데이트

A vulnerable transitive dependency and its fix path An app declares two direct dependencies, express and hbs. Express brings in body-parser and send, which bring in raw-body and mime-types. Hbs brings in handlebars, which is vulnerable. The path from the app through hbs to handlebars is highlighted: upgrade hbs, or override the handlebars version. your project direct transitive, depth 1 depth 2 my-app express hbs body-parser send handlebars vulnerable, required by hbs raw-body mime-types Fix path: upgrade hbs, or override the handlebars version

직접 종속성과 전이적 종속성

직접 종속성은 매니페스트에 직접 선언한 종속성입니다. 전이적 종속성은 종속성이 선언한 종속성, 그리고 그 종속성이 다시 선언한 종속성으로, 트리가 깊어지는 만큼 계속 이어집니다. 패키지 관리자는 설치할 때 트리 전체를 해석하며, 보통 그 결과를 잠금 파일에 기록합니다.

패키지 하나, express만 선언한 앱을 예로 들어 보겠습니다. npm ls --all을 실행하면 그 한 줄이 무엇을 함께 가져오는지 볼 수 있습니다.

my-app
└─┬ express            ← 직접: 사용자가 선언함
  ├─┬ body-parser      ← 전이적, 깊이 1
  │ └── raw-body       ← 전이적, 깊이 2
  ├── cookie           ← 전이적, 깊이 1
  └─┬ send             ← 전이적, 깊이 1
    └── mime-types     ← 전이적, 깊이 2

실제 트리는 더 깁니다. 일반적인 애플리케이션의 패키지 대부분은 이런 식으로 들어오며, 이는 출시하는 코드의 대부분을 직접 고른 것이 아니라 패키지 관리자가 골랐다는 뜻입니다.

직접 종속성 전이적 종속성
선택한 주체 팀이 매니페스트에서 종속성의 매니페스트를 바탕으로 패키지 관리자가
기재 위치 매니페스트와 잠금 파일 잠금 파일(있는 경우)
버전을 통제하는 주체 사용자 재정의하지 않는 한 상위 패키지의 버전 범위
취약점 수정 방법 업그레이드 상위 패키지 업그레이드 또는 버전 재정의

전이적 종속성이 중요한 이유

전이적 종속성은 직접 종속성과 같은 위험을 안고 있지만, 가시성과 통제력은 더 낮습니다.

  • 취약점. log4j의 제로데이인 Log4Shell이 공개되었을 때, Google의 Open Source Insights 팀은 영향을 받는 log4j 코드에 의존하는 Maven Central 아티팩트 35,863개를 찾아냈습니다. 그중 약 7,000개가 직접 의존했습니다. 대다수는 전이적 종속성으로 이를 가져왔으며, 상당수는 중간에 있는 패키지가 먼저 수정 버전을 내놓기 전까지 수정할 수 없었습니다.
  • 공급망 공격. xz utils 백도어(CVE-2024-3094)는 OpenSSH가 xz에 의존하지 않았는데도 OpenSSH에 도달했습니다. 여러 Linux 배포판이 systemd 알림을 지원하도록 OpenSSH를 패치하는데, libsystemd가 xz가 제공하는 라이브러리인 liblzma에 의존하기 때문입니다.
  • 라이선스. 모든 전이적 패키지에는 자체 라이선스가 있습니다. 세 단계 아래에 있는 카피레프트 라이선스도 직접 추가한 라이선스와 똑같이 구속력이 있습니다.
  • 호환성을 깨는 변경. 버전 범위를 허용하는 상위 패키지는 매니페스트에 아무 변화가 없어도 다음 새 설치 때 새로운 전이적 릴리스를 들여옵니다.

전이적 종속성 목록을 확인하는 방법

주요 패키지 관리자는 모두 해석된 트리를 출력할 수 있습니다.

생태계 명령
npmnpm ls --all
pnpmpnpm list --depth Infinity
Python (uv)uv tree
Python (pip)pipdeptree
Gogo mod graph
Rustcargo tree
Mavenmvn dependency:tree
Gradlegradle dependencies

특정 패키지가 왜 들어와 있는지 알고 싶다면 그 패키지까지의 경로를 확인하세요. npm explain <package>, pnpm why, yarn why, cargo tree -i <crate>를 사용합니다. 경로를 출력하는 대신 다루고 싶다면 종속성 그래프를 참고하세요.

취약한 전이적 종속성을 수정하는 방법

  1. 상위 패키지를 업그레이드하세요. 해당 패키지를 가져오는 직접 종속성을 찾아 수정된 버전을 요구하는 릴리스로 옮깁니다. 상위 패키지의 메인테이너가 테스트를 마쳤으므로 가장 깔끔한 수정 방법입니다.
  2. 잠금 파일을 갱신하세요. 상위 패키지의 버전 범위가 이미 수정된 버전을 허용한다면 잠금 파일 항목만 업데이트하면 됩니다. 예를 들어 cargo update -p <crate>를 실행하거나 npm update를 새로 실행합니다.
  3. 버전을 재정의하세요. 상위 패키지가 수정 버전을 내놓지 않았다면 직접 버전을 강제하세요. npm과 pnpm에서는 overrides, Yarn에서는 resolutions, pip에서는 constraints 파일, 또는 go.mod에 더 높은 요구 버전을 지정합니다. 상위 패키지가 그 버전으로 릴리스된 적이 없으므로 반드시 테스트하세요.
  4. 상위 패키지를 교체하거나 제거하세요. 어느 방법도 통하지 않는다면, 해당 패키지를 들여오는 종속성은 더 이상 유지할 가치가 없을 수 있습니다.

일부 소프트웨어 구성 분석 도구는 코드가 취약한 함수를 호출할 수 있는지 확인하는 도달 가능성 분석을 추가해, 이 중 어떤 수정을 먼저 할지 결정하도록 돕습니다. 선택지는 SCA 도구 비교를 참고하세요.

잠금 파일만으로는 전부가 아닌 이유

대부분의 도구는 잠금 파일에서 전이적 종속성 정보를 구성합니다. 잠금 파일이 존재하고, 최신 상태이며, 빌드가 그 파일만을 기준으로 설치할 때는 이 방식이 통합니다. CI에서는 그렇지 않은 경우가 많습니다.

  • 잠금 파일이 없는 경우. 버전 범위가 적힌 requirements.txt나 잠금 파일을 커밋한 적이 없는 프로젝트는 빌드할 때마다 새로 해석되므로, 전이적 버전이 빌드마다 달라질 수 있습니다.
  • 캐시. CI 캐시는 패키지를 다운로드하는 대신 이전 실행에서 복원하며, 그 내용이 항상 현재 잠금 파일과 일치하지는 않습니다. GitHub Actions 캐시가 감추는 것을 참고하세요.
  • 빌드 도구. 린터, 컴파일러, 코드 생성기, 설정 단계는 각자의 종속성 트리를 빌드에 들여옵니다. 애플리케이션 매니페스트에는 없지만 소스와 시크릿에 접근할 수 있는 상태로 실행됩니다.
  • 설치 스크립트와 다운로드. 패키지의 설치 스크립트는 코드를 추가로 다운로드할 수 있고, 빌드 단계는 바이너리를 직접 다운로드할 수 있습니다. 어느 쪽도 잠금 파일에 항목을 남기지 않습니다.

릴리스에 어떤 전이적 종속성이 들어갔는지에 대한 유일하게 완전한 기록은 그 릴리스를 빌드하는 동안 남긴 기록입니다. 빌드를 기록하는 것과 나중에 파일을 스캔하는 것의 차이는 빌드 시점 SBOM에서 설명합니다.

전이적 종속성과 CRA

EU Cyber Resilience Act는 제조업체에 "at the very least the top-level dependencies of the products"(최소한 제품의 최상위 종속성)를 포함하는 SBOM을 작성하도록 요구합니다(부속서 I, 파트 II, 1항). 전이적 종속성은 명시되어 있지 않으므로, 법적 최저 기준은 많은 가이드가 시사하는 것보다 낮습니다. 하지만 CRA는 제품에 포함된 구성 요소의 취약점을 식별하고 처리하도록 요구하며, 취약한 전이적 패키지도 그 구성 요소에 해당합니다. 첫 번째 단계에서 멈추는 SBOM은 종속성 트리의 대부분을 그 프로세스에서 빠뜨립니다. 자세한 내용은 CRA SBOM 요구사항을 참고하세요.

CRACI가 전이적 종속성을 추적하는 방법

CRACI는 빌드를 스캔하는 대신 기록하는 GitHub Actions 러너입니다. 각 작업이 실행되는 동안 패키지를 인식하는 프록시가 CI 캐시에서 복원된 패키지를 포함해 트리의 모든 깊이에서 작업이 다운로드하는 모든 패키지를 기록합니다. 그 결과 스캐너 기반 도구보다 실제로 사용되는 종속성을 더 완전하게 파악할 수 있습니다.

  • 모든 깊이를 정직하게 명시. 각 작업의 SBOM에는 완전성 상태가 포함되어, 기록이 모든 것을 보지 못한 경우를 알 수 있습니다.
  • 트리 시각화. 종속성 그래프가 SBOM의 종속성 계층을 여러 뷰로 보여 줍니다.
  • 전이적 종속성을 포함한 내보내기. CycloneDX 및 SPDX 내보내기에는 각각의 선언된 라이선스와 함께 전이적 종속성이 포함됩니다.
  • 영향을 받은 빌드 확인. 새로운 취약점이 발표되면 빌드 기록에서 과거의 어떤 빌드에 직접 또는 전이적인 취약한 패키지가 포함되었는지 확인할 수 있으므로, 그 패키지를 출시한 기간을 알 수 있습니다(CVE의 영향을 받았는가? 참고). 기록은 보존 기간 설정을 따르며 기본값은 180일입니다.
  • 정책 게이트. 특정 CVE가 포함된 빌드는 출시 전에 차단할 수 있습니다.

CRACI는 도달 가능성 분석을 하지 않습니다. 코드가 취약한 함수를 호출하는지 알아야 한다면 이를 지원하는 SCA 도구와 함께 사용하세요. CRACI의 SBOM 생성을 참고하거나, 데모를 예약해 빌드 하나를 직접 기록해 보세요.

전이적 종속성: 자주 묻는 질문

전이적 종속성이란 무엇입니까?

전이적 종속성은 다른 패키지가 필요로 하기 때문에 소프트웨어가 사용하게 되는 패키지입니다. 앱이 라이브러리 A에 의존하고 A가 라이브러리 B에 의존한다면, B는 앱의 전이적(간접) 종속성입니다. 직접 선언한 적은 없지만 소프트웨어와 함께 출시됩니다.

직접 종속성과 전이적 종속성의 차이는 무엇입니까?

직접 종속성은 package.json, pyproject.toml, go.mod 같은 매니페스트에 직접 선언한 종속성입니다. 전이적 종속성은 직접 종속성이 선언한 종속성으로, 깊이에 관계없이 해당됩니다. 직접 종속성은 개발자가 고르고, 전이적 종속성은 패키지 관리자가 트리를 해석할 때 고릅니다.

Transient dependency와 transitive dependency는 같은 것입니까?

실무적으로는 그렇습니다. "Transient dependency"는 "transitive dependency"를 잘못 쓴 흔한 표현입니다. 올바른 용어는 추이 관계(transitive relation)에서 온 transitive입니다. A가 B에 의존하고 B가 C에 의존하면 A는 C에 의존합니다.

전이적 종속성의 취약점은 어떻게 수정합니까?

먼저 수정된 버전을 포함한 릴리스가 있다면, 해당 패키지를 가져오는 직접 종속성을 업그레이드하세요. 그런 릴리스가 없다면 npm overrides, Yarn resolutions, pip constraints 파일 같은 패키지 관리자의 재정의 기능으로 수정된 버전을 강제하고, 상위 패키지가 그 버전에서도 작동하는지 테스트하세요.

모든 전이적 종속성 목록은 어떻게 확인합니까?

모든 패키지 관리자는 해석된 트리를 출력할 수 있습니다. npm ls --all, pnpm list --depth Infinity, uv tree 또는 pipdeptree, go mod graph, cargo tree, mvn dependency:tree, gradle dependencies를 사용합니다. 프로덕션 빌드가 실제로 무엇을 설치했는지 알려면 빌드 자체를 기록하세요.

EU Cyber Resilience Act는 SBOM에 전이적 종속성을 요구합니까?

규정은 최저 기준을 "at the very least the top-level dependencies of the products"(최소한 제품의 최상위 종속성)로 정합니다(부속서 I, 파트 II, 1항). 전이적 종속성은 명시되어 있지 않지만, 취약한 전이적 패키지도 여전히 제품 안에 있으며, CRA는 출시하는 구성 요소의 취약점을 처리하도록 요구합니다.

빌드가 가져온 모든 종속성을 확인하세요

GitHub Actions 워크플로 하나를 CRACI에서 실행하고, 트리의 모든 깊이에서 다운로드한 모든 패키지가 기록된 SBOM을 받아 보세요.

데모 예약