SBOM을 사용한 의존성 스캔
GitLab v19.5Offering: GitLab Self-Managed
요약
CycloneDX 소프트웨어 자재 명세서(SBOM)를 사용한 의존성 스캔은 애플리케이션의 의존성에서 알려진 취약점을 분석합니다. 의존성 스캔은 흔히 소프트웨어 구성 분석(SCA)의 일부로 여겨집니다. 의존성 스캔은 애플리케이션 수명 주기의 개발 단계에서 실행할 수 있습니다.
히스토리
- GitLab 17.4에서 기본 브랜치에 한해 실험 기능으로 도입되었습니다.
dependency_scanning_using_sbom_reports라는 기능 플래그를 사용하며 기본적으로 비활성화되어 있습니다. - GitLab 17.5에서 GitLab Self-Managed에 활성화되었습니다.
- GitLab 17.9에서 실험 기능에서 베타로 변경되어 모든 브랜치를 지원하며, Cargo, Conda, Cocoapods, Swift에 대해 최신 의존성 스캔 CI/CD 템플릿에서 기본적으로 활성화됩니다.
- GitLab 17.10에서
dependency_scanning_using_sbom_reports기능 플래그가 제거되었습니다. - GitLab 18.5에서 베타에서 GitLab.com 한정 제한적 제공으로 변경되었으며, 새로운 V2 CI/CD 의존성 스캔 템플릿이 함께 제공됩니다.
dependency_scanning_sbom_scan_api라는 기능 플래그를 사용하며 기본적으로 비활성화되어 있습니다. - GitLab 18.10에서
dependency_scanning_using_sbom_reports기능 플래그가 기본적으로 활성화되었습니다. - GitLab 19.0에서 정식 출시되었습니다.
CycloneDX 소프트웨어 자재 명세서(SBOM)를 사용한 의존성 스캔은 애플리케이션의 의존성에서 알려진 취약점을 분석합니다. 모든 의존성이 스캔 대상이며, 전이 의존성도 포함됩니다.
의존성 스캔은 흔히 소프트웨어 구성 분석(SCA)의 일부로 여겨집니다. SCA에는 코드가 사용하는 항목을 점검하는 여러 측면이 포함될 수 있습니다. 이러한 항목에는 대개 애플리케이션 및 시스템 의존성이 포함되며, 이는 직접 작성한 항목이 아니라 거의 항상 외부 출처에서 가져온 것입니다.
의존성 스캔은 애플리케이션 수명 주기의 개발 단계에서 실행할 수 있습니다. CI/CD 파이프라인에서 새 의존성 스캔 분석기를 사용하면 프로젝트 의존성이 탐지되어 CycloneDX SBOM 보고서에 기록됩니다. 보안 결과는 소스 브랜치와 대상 브랜치 사이에서 식별되고 비교됩니다. 결과와 심각도는 머지 리퀘스트에 나열되므로, 코드 변경이 커밋되기 전에 애플리케이션의 위험에 선제적으로 대응할 수 있습니다. 보고된 SBOM 컴포넌트의 보안 결과는 새 보안 어드바이저리가 게시될 때 지속적 취약점 스캔에서도 CI/CD 파이프라인과 별개로 식별됩니다.
GitLab은 의존성 스캔과 컨테이너 스캔을 모두 제공하여 이러한 모든 의존성 유형을 포괄합니다. 위험 영역을 최대한 넓게 다루려면 모든 보안 스캐너를 함께 사용하기를 권장합니다. 이 기능들의 비교는 의존성 스캔과 컨테이너 스캔 비교를 참고합니다.
새 의존성 스캔 분석기에 대한 의견은 이 피드백 이슈에 남깁니다.
의존성 스캔 활성화#
프로젝트에서 의존성 스캔을 활성화합니다.
사전 요구 사항#
모든 GitLab 인스턴스 공통 사전 요구 사항은 다음과 같습니다.
- 프로젝트에 대한 Developer, Maintainer 또는 Owner 권한.
- 리포지터리에 커밋했거나 CI/CD 파이프라인에서 생성하여 아티팩트로
dependency-scanningjob에 전달한 지원되는 잠금 파일 또는 의존성 그래프 내보내기. 또는 의존성 해석으로 지원되는 에코시스템에 필요한 파일을 생성할 수 있으며, 매니페스트 파일을 폴백으로 사용할 수도 있습니다. - 자체 관리 러너의 경우
docker또는kubernetes실행기를 사용하는 GitLab Runner. - GitLab.com의 호스티드 러너는 이 구성이 기본적으로 활성화되어 있습니다.
GitLab Self-Managed에만 해당하는 사항으로, 스캔할 모든 PURL 유형의 패키지 메타데이터를 GitLab 인스턴스에 동기화해야 합니다. GitLab 인스턴스에 이 데이터가 없으면 의존성 스캔이 취약점을 식별할 수 없습니다.
프로젝트 파이프라인 구성 업데이트#
의존성 스캔을 활성화하려면 프로젝트 파이프라인 구성에 의존성 스캔 템플릿을 추가해야 합니다.
기본적으로 Dependency-Scanning.v2.gitlab-ci.yml 템플릿은 머지 리퀘스트 파이프라인에서 의존성 스캔 job을
실행합니다. 프로젝트가 다른 job에 머지 리퀘스트 파이프라인을 사용하지 않으면,
머지 리퀘스트 파이프라인에는 의존성 스캔 job만 나타나고 나머지 job은
별도의 브랜치 파이프라인에서 실행됩니다. 이 동작을 비활성화하려면
의존성 스캔의 머지 리퀘스트 파이프라인 비활성화를 참고합니다.
GitLab UI에서 의존성 스캔을 활성화하려면 다음과 같이 합니다.
-
상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
-
왼쪽 사이드바에서 Code > Repository를 선택합니다.
-
.gitlab-ci.yml파일을 선택합니다. -
Edit > Edit single file을 선택합니다.
-
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.include: - template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml -
Commit changes를 선택합니다.
사용 가능한 컨테이너 이미지#
이 기능은 컨테이너 이미지를 사용해 CI job을 실행합니다. 기본 CI job
정의는 이 이미지를 메이저 버전 태그
(예: dependency-scanning:2)로 참조하므로,
CI/CD 구성을 변경하지 않아도 패치 및 마이너 업데이트를 자동으로 받습니다.
유지 관리 정책#
GitLab은 릴리스 및 유지 관리 정책에 따라 현재 안정 릴리스에는 버그 수정을, 이전 두 개의 월간 릴리스에는 보안 수정을 제공합니다.
CI/CD job은 이미지를 메이저 버전 태그(예: dependency-scanning:2)로 참조하므로,
해당 메이저 이미지 버전과 호환되는 모든 GitLab 버전에서 수정 사항을 자동으로
사용할 수 있습니다.
이 정책은 아래에 나열된 이미지에 적용됩니다. 이전 이미지는 이 정책의 적용 대상이 아닙니다.
현재 이미지#
| CI/CD job | 프로덕션 이미지 | GitLab 버전 |
|---|---|---|
dependency-scanning |
registry.gitlab.com/security-products/dependency-scanning:2 |
19.x |
dependency-scanning:maven-resolution |
registry.gitlab.com/security-products/dependency-resolution/ubi9/openjdk-21:1 |
18.x, 19.x |
dependency-scanning:gradle-resolution |
registry.gitlab.com/security-products/dependency-resolution/ubi9/openjdk-17-with-gradle-8:1 |
19.x |
dependency-scanning:python-resolution |
registry.gitlab.com/security-products/dependency-resolution/ubi9/python-312-minimal-with-piptools-7:9 |
18.x,19.x |
현재 이미지는 기본 이미지 공급업체의 업스트림 패치를 반영하기 위해 정기적으로 다시 빌드됩니다.
이전 이미지#
이 이미지는 더 이상 사용되지 않으며 버그 수정이나 새 기능을 받지 않습니다. 컨테이너 레지스트리에는 계속 남아 있고 해당하는 GitLab 버전에서는 계속 동작합니다. 사용 중단된 이미지를 더 새로운 GitLab 버전과 함께 사용하는 것은 지원되지 않으며 예기치 않은 결과가 발생할 수 있습니다.
| CI/CD job | 프로덕션 이미지 | GitLab 버전 | 사용 중단 버전 |
|---|---|---|---|
dependency-scanning |
registry.gitlab.com/security-products/dependency-scanning:1 |
18.x |
19.0 |
dependency-scanning |
registry.gitlab.com/security-products/dependency-scanning:0 |
18.x |
19.0 |
FIPS 준수#
의존성 스캔 분석기 이미지와 모든 의존성 해석 이미지는 FIPS 140 검증을 받은 암호화 모듈을 사용하는 Red Hat UBI를 기반으로 합니다. FIPS가 활성화된 환경에서도 추가 구성이 필요하지 않습니다.
결과 이해#
의존성 스캔 분석기의 출력은 다음과 같습니다.
- 탐지된 지원 잠금 파일 또는 의존성 그래프 내보내기마다 하나씩 생성되는 CycloneDX SBOM.
- 스캔한 모든 SBOM 문서에 대한 단일 의존성 스캔 보고서.
분석기가 지원되는 파일을 하나도 찾지 못하면, 의존성 스캔 job은 정상적으로 완료되고 CI/CD job 로그에 경고를 출력합니다. 이 경우 CycloneDX SBOM이나 의존성 스캔 보고서는 생성되지 않습니다.
CycloneDX 소프트웨어 자재 명세서#
의존성 스캔 분석기는 지원되는 잠금 파일, 의존성 그래프 또는 매니페스트 파일이 탐지된 디렉터리마다 CycloneDX 소프트웨어 자재 명세서(SBOM)를 출력합니다. CycloneDX SBOM은 job 아티팩트로 생성됩니다.
CycloneDX SBOM의 특징은 다음과 같습니다.
- 이름은
gl-sbom-<package-type>-<package-manager>.cdx.json형식입니다. - 의존성 스캔 job의 job 아티팩트로 제공됩니다.
cyclonedx보고서로 업로드됩니다.- 탐지된 잠금 파일 또는 의존성 그래프 파일과 같은 디렉터리에 저장됩니다.
예를 들어 프로젝트의 구조가 다음과 같다고 가정합니다.
.
├── ruby-project/
│ └── Gemfile.lock
├── ruby-project-2/
│ └── Gemfile.lock
└── php-project/
└── composer.lock
이 경우 다음 CycloneDX SBOM이 job 아티팩트로 생성됩니다.
.
├── ruby-project/
│ ├── Gemfile.lock
│ └── gl-sbom-gem-bundler.cdx.json
├── ruby-project-2/
│ ├── Gemfile.lock
│ └── gl-sbom-gem-bundler.cdx.json
└── php-project/
├── composer.lock
└── gl-sbom-packagist-composer.cdx.json
의존성 스캔 보고서#
의존성 스캔 분석기는 CycloneDX SBOM 파일에서 식별된 의존성의 모든 취약점을 기록하는 의존성 스캔 보고서를 생성합니다.
의존성 스캔 보고서의 특징은 다음과 같습니다.
- 이름은
gl-dependency-scanning-report.json입니다. - 의존성 스캔 job의 job 아티팩트로 제공됩니다.
dependency_scanning보고서로 업로드됩니다.- 프로젝트의 루트 디렉터리에 저장됩니다.
악성 패키지#
의존성 스캔은 CycloneDX SBOM을 수집할 때 악성 패키지를 식별합니다. GitLab은 SBOM의 컴포넌트를 일반 보안 어드바이저리와 함께 GitLab 악성코드 어드바이저리와 비교합니다. 일치하는 항목이 있으면 취약점이 생성됩니다.
악성 패키지 결과는 공격자가 악용할 수 있는 결함이 패키지에 있다는 뜻이 아니라, 패키지 자체가 유해하다는 뜻입니다. 이는 패키지가 인기 있는 패키지의 이름을 흉내 내는 타이포스쿼팅을 하거나, 탈취된 메인테이너 계정이 유해한 릴리스를 게시하거나, 패키지에 악성코드처럼 동작하도록 작성된 코드가 들어 있을 때 발생합니다. 이 결과는 특정 결함이 아니라 패키지를 기술하므로, CVE 레코드에 기반한 결과와 달리 취약점이 먼저 공개되어 있어야 탐지되는 것은 아닙니다.
악성 패키지 결과의 취약점 세부 정보 페이지에는 해결 방법이 없으며, CVSS, Exploit Prediction Scoring System(EPSS), Known Exploited Vulnerabilities(KEV) 정보도 포함되지 않습니다. 악성코드 어드바이저리에는 이러한 데이터가 없습니다. 이 필드들은 결함을 얼마나 악용할 수 있는지와 어떻게 고치는지를 설명하는데, 그 자체로 악성인 패키지에는 둘 다 해당하지 않습니다. 악성 패키지 결과를 해결하려면 패키지를 업그레이드하지 말고 프로젝트에서 제거합니다.
이러한 취약점의 심각도는 항상 Critical입니다. 악성코드 어드바이저리는 Common Vulnerability Scoring System(CVSS) 점수에서
심각도를 도출하지 않고 심각도를 직접 명시합니다.
각 취약점에는 GLAM-<year>-<month>-<sequence> 형식의 식별자가 있으며, 예를 들면
GLAM-2026-09-00138입니다. Common Vulnerabilities and Exposures(CVE) 식별자는 없습니다.
악성코드 어드바이저리가 다루는 패키지 유형은 의존성 스캔이 일반적으로 지원하는 유형보다 적습니다. 전체 목록은 지원되는 패키지 유형을 참고합니다.
이 기능은 GitLab Ultimate에서 사용할 수 있으며 별도로 켜는 설정이 없습니다. 프로젝트의 기존 의존성 스캔 구성을 따릅니다. GitLab Self-Managed에서는 다루는 패키지 레지스트리도 패키지 메타데이터 동기화를 따르며, 이는 사전 요구 사항에 설명되어 있습니다.
GitLab이 악성코드 어드바이저리를 철회하면 해당 어드바이저리와의 일치 검사를 중단하고 그로부터 새 취약점을 생성하지 않습니다.
지속적 취약점 스캔은 파이프라인을 실행하지 않고도 같은 일치 검사를 수행합니다.
악성코드 결과는 취약점 보고서와 의존성 목록에 표시됩니다. 두 곳 모두 영향을 받은 취약점이나 의존성에 빨간색 악성코드 배지가 나타나며, 악성코드 상태로 필터링할 수도 있습니다.
알려진 제한 사항#
의존성 스캔의 악성코드 일치 검사에는 다음과 같은 제한 사항이 있습니다.
- GitLab은 기본 브랜치의 컴포넌트만 평가하며, 다른 브랜치의 컴포넌트에 대해서는 결과를 생성하지 않습니다.
- 이미 사용 중인 패키지에 대해 새 악성코드 어드바이저리가 게시되어도 GitLab이 선제적으로 알리지 않습니다. 취약점 보고서를 다음에 검토할 때 해당 결과를 확인하게 됩니다.
- 결과에 같은 어드바이저리 ID가 두 번 나열되는데, 한 번은
GLAM-<year>-<month>-<sequence>이고 한 번은Gemnasium-GLAM-<year>-<month>-<sequence>식별자입니다. 반복된 항목은 식별자가 표시되는 방식에만 영향을 주며 탐지나 중복 제거에는 영향을 주지 않습니다. 자세한 내용은 이슈 627314를 참고합니다. - GitLab은 이후 철회된 어드바이저리에서 생성된 취약점을 해결 처리하지 않습니다. 해당 취약점은 직접 해결하기 전까지 취약점 보고서에 남아 있습니다. 자세한 내용은 이슈 612099를 참고합니다.
스캔 성능 향상#
의존성 스캔 성능을 좌우하는 주된 요인은 스캔할 의존성의 수입니다. 기본적으로 의존성 스캔은 다음 범위로 동작합니다.
- 지원되는 모든 언어와 파일이 포함됩니다.
- 루트 디렉터리와 그 바로 아래 하위 디렉터리가 포함됩니다.
- 숨김 디렉터리는 제외됩니다.
성능을 높이려면 특정 경로를 제외하거나, 스캔 디렉터리 깊이를 제한하거나, 개발 및 테스트 의존성을 제외할 수 있습니다.
스캔 제한#
각 프로젝트에는 파이프라인 전반에 걸쳐 시간당 SBOM 스캔 50건의 소프트 스로틀이 있습니다. 이를 초과하는 스캔은 더 낮은 우선순위로 수락되며, 모노레포 같은 대용량 프로젝트에서는 스캔 소요 시간이 늘어날 수 있습니다.
이 스로틀은 구성할 수 없습니다. 자세한 내용은 SBOM을 사용하는 의존성 스캔 제한을 참고합니다.
스캔에서 경로 제외#
스캔 성능을 높이려면 경로를 제외합니다. 예를 들어 문서가 들어 있는 경로를 제외할 수 있습니다. 경로를 제외할 때는 취약점이 가려지지 않도록 신중하게 선택합니다.
제외할 경로는 .gitlab-ci.yml 파일에 나열합니다.
- 의존성 스캔 템플릿에서는
DS_EXCLUDED_PATHSCI/CD 변수를 사용합니다. - 의존성 스캔 CI/CD 컴포넌트에서는
excluded_pathsspec 입력을 사용합니다.
패턴을 여러 개 지정하려면 공백 없이 쉼표로 구분합니다. 예를 들면 다음과 같습니다.
variables:
DS_EXCLUDED_PATHS: "**/*.Test/**,**/*.Test.*/**,src/Test/**"
제외 패턴은 다음 규칙을 따릅니다.
- 슬래시가 없는 패턴은 프로젝트의 모든 깊이에 있는 파일 또는 디렉터리 이름과 일치합니다. 예를 들어
test는./test와src/test에 일치합니다. - 슬래시가 있는 패턴은 해당 패턴으로 시작하는 경로에 일치합니다. 예를 들어
a/b는a/b와a/b/c에 일치하지만c/a/b에는 일치하지 않습니다. - 표준 glob 와일드카드를 지원합니다. 예를 들어
a/**/b는a/b,a/x/b,a/x/y/b에 일치합니다. - 앞뒤 슬래시는 무시됩니다. 예를 들어
/build와build/는build와 같은 결과에 일치합니다. - 쉼표 뒤의 공백은 패턴의 일부가 되어 일치에 실패하게 합니다.
"path/a/**, path/b/**"가 아니라"path/a/**,path/b/**"를 사용합니다.
스캔 디렉터리 깊이 제한#
기본적으로 스캔은 리포지터리의 루트 디렉터리와 그 바로 아래 하위 디렉터리에서만 패키지 관리자
파일을 검색합니다. 스캔 성능을 높이려면 최대 디렉터리 깊이를 1로 설정하여 검색을 리포지터리의 루트 디렉터리로만 제한합니다. 리포지터리의 관련 패키지 관리자 파일을
모두 포함하도록 주의합니다.
.gitlab-ci.yml 파일에서 최대 스캔 디렉터리 깊이를 지정하려면 다음과 같이 합니다.
- 의존성 스캔 템플릿에서는
DS_MAX_DEPTHCI/CD 변수를 사용합니다. - 의존성 스캔 CI/CD 컴포넌트에서는
max_scan_depthspec 입력을 사용합니다.
다음 예시에서는 DS_MAX_DEPTH를 1로 설정했으므로 의존성 스캔이 timer 디렉터리에서만
패키지 관리자 파일을 검색합니다. 하위 디렉터리는 스캔하지 않습니다.
timer
├── integration
└── source
개발 및 테스트 의존성 제외#
기본적으로 개발 및 테스트 의존성이 스캔에 포함됩니다. 스캔 성능을 높이려면 다음 중 하나를 설정하여 이를 제외합니다.
- CI/CD 변수
DS_INCLUDE_DEV_DEPENDENCIES를"false"로 설정 - CI/CD 컴포넌트 입력
include_dev_dependencies를 false로 설정
다음 패키지 관리자를 사용하는 프로젝트만 지원됩니다: Composer, Conda, Gradle, Maven, npm, pnpm, Pipenv, Poetry, uv.
롤아웃#
단일 프로젝트에서 SBOM을 사용한 의존성 스캔 결과에 확신이 생기면 여러 프로젝트와 그룹으로 적용 범위를 확장할 수 있습니다. 자세한 내용은 여러 프로젝트에서 스캔 적용을 참고합니다.
고유한 요구 사항이 있다면 SBOM을 사용한 의존성 스캔을 오프라인 환경에서 실행할 수 있습니다.
지원되는 패키지 유형#
보안 분석이 효과를 내려면 SBOM 보고서에 나열된 컴포넌트가 GitLab 어드바이저리 데이터베이스에 해당 항목을 가지고 있어야 합니다.
GitLab SBOM 취약점 스캐너는 다음 PURL 유형의 컴포넌트에 대해 의존성 스캔 취약점을 보고할 수 있습니다.
cargocomposerconangemgolangmavennpmnugetpypiswift
지원되는 언어 및 파일#
히스토리
- GitLab 19.2에서 Bun 지원이 도입되었습니다.
| 언어 | 패키지 매니저 | 파일 | 설명 | 의존성 그래프 내보내기 지원 | 정적 도달 가능성 지원 |
|---|---|---|---|---|---|
| C# | NuGet | packages.lock.json |
nuget으로 생성된 잠금 파일. |
✅ | ❌ |
| C/C++ | Conan | conan.lock |
conan으로 생성된 잠금 파일. |
✅ | ❌ |
| C/C++/Fortran/Go/Python/R | Conda | conda-lock.yml |
conda-lock으로 생성된 환경 파일. |
❌ | ❌ |
| Dart | pub | pubspec.lock, pub.graph.json |
pub으로 생성된 잠금 파일. dart pub deps --json > pub.graph.json에서 파생된 의존성 그래프 내보내기. |
✅ | ❌ |
| Go | go | go.mod, go.graph |
표준 go 툴체인으로 생성된 모듈 파일. go mod graph > go.graph에서 파생된 의존성 그래프 내보내기. |
✅ | ❌ |
| Java | ivy | ivy-report.xml |
Apache Ant report 태스크로 생성된 의존성 그래프 내보내기. |
❌ | ✅ |
| Java | Maven | maven.graph.json |
mvn dependency:tree -DoutputType=json으로 생성된 의존성 그래프 내보내기. |
✅ | ✅ |
| Java | Maven | pom.xml |
의존성 해석에 사용되거나, 의존성 그래프 내보내기가 없을 때 매니페스트 폴백으로 사용되는 Maven 매니페스트 파일. | ❌ | ✅ |
| Java/Kotlin | Gradle | gradle.graph.txt |
./gradlew dependencies로 생성된 의존성 그래프 내보내기. |
✅ | ✅ |
| Java/Kotlin | Gradle | dependencies.lock, dependencies.direct.lock |
gradle-dependency-lock-plugin으로 생성된 잠금 파일. | ✅ | ✅ |
| Java/Kotlin | Gradle | gradle.lockfile |
gradle dependencies --write-locks로 생성된 잠금 파일. |
❌ | ✅ |
| Java/Kotlin | Gradle | gradle-html-dependency-report.js |
htmlDependencyReport 태스크로 생성된 의존성 그래프 내보내기. | ✅ | ✅ |
| Java/Kotlin | Gradle | build.gradle, build.gradle.kts |
의존성 해석에 사용되거나, 잠금 파일이나 의존성 그래프 내보내기가 없을 때 매니페스트 폴백으로 사용되는 Gradle 빌드 파일. | ❌ | ✅ |
| JavaScript/TypeScript | Bun | bun.lock |
bun으로 생성된 잠금 파일. |
✅ | ✅ |
| JavaScript/TypeScript | npm | package-lock.json, npm-shrinkwrap.json |
npm v5 이상으로 생성된 잠금 파일(lockfileVersion 속성을 생성하지 않는 이전 버전은 지원되지 않음). |
✅ | ✅ |
| JavaScript/TypeScript | pnpm | pnpm-lock.yaml |
pnpm으로 생성된 잠금 파일. |
✅ | ✅ |
| JavaScript/TypeScript | yarn | yarn.lock |
yarn으로 생성된 잠금 파일. |
✅ | ✅ |
| Objective-C | CocoaPods | Podfile.lock |
cocoapods로 생성된 잠금 파일. 탐지 전용: SBOM은 생성되지만 CocoaPods 컴포넌트는 의존성 목록에 나타나지 않고, 취약점 어드바이저리와 대조되지 않으며, 라이선스 스캔에도 포함되지 않습니다.1 |
❌ | ❌ |
| PHP | composer | composer.lock |
composer로 생성된 잠금 파일. |
✅ | ❌ |
| Python | pip | pipdeptree.json |
pipdeptree --json으로 생성된 의존성 그래프 내보내기. |
✅ | ✅ |
| Python | pip | requirements.txt (lockfile) |
pip-compile로 생성된 잠금 파일. |
✅ | ✅ |
| Python | pip | requirements.txt |
의존성 해석에 사용되거나, 잠금 파일이나 의존성 그래프 내보내기가 없을 때 매니페스트 폴백으로 사용되는 매니페스트 파일. | ❌ | ❌ |
| Python | pipenv | Pipfile.lock |
pipenv로 생성된 잠금 파일. |
❌ | ❌ |
| Python | pipenv | pipenv.graph.json |
pipenv graph --json-tree >pipenv.graph.json으로 생성된 의존성 그래프 내보내기. |
✅ | ✅ |
| Python | poetry | poetry.lock |
poetry v1 또는 v2로 생성된 잠금 파일. |
✅ | ✅ |
| Python | uv2 | uv.lock |
uv로 생성된 잠금 파일. |
✅ | ✅ |
| Ruby | bundler | Gemfile.lock, gems.locked |
bundler로 생성된 잠금 파일. |
✅ | ❌ |
| Rust | cargo | Cargo.lock |
cargo로 생성된 잠금 파일. |
✅ | ❌ |
| Scala | sbt | dependencies-compile.dot |
sbt dependencyDot으로 생성된 의존성 그래프 내보내기. |
✅ | ❌ |
| Swift | swift | Package.resolved |
swift로 생성된 잠금 파일. |
❌ | ❌ |
패키지 해시 정보#
의존성 스캔 SBOM에는 사용 가능한 경우 패키지 해시 정보가 포함됩니다. 이 정보는 NuGet 패키지에만 제공됩니다. 패키지 해시는 SBOM의 다음 위치에 나타나며, 이를 통해 패키지의 무결성과 진위를 확인할 수 있습니다.
- 전용 해시 필드
- PURL 한정자
예를 들면 다음과 같습니다.
{
"name": "Iesi.Collections",
"version": "4.0.4",
"purl": "pkg:nuget/Iesi.Collections@4.0.4?sha512=8e579b4a3bf66bb6a661f297114b0f0d27f6622f6bd3f164bef4fa0f2ede865ef3f1dbbe7531aa283bbe7d86e713e5ae233fefde9ad89b58e90658ccad8d69f9",
"hashes": [
{
"alg": "SHA-512",
"content": "8e579b4a3bf66bb6a661f297114b0f0d27f6622f6bd3f164bef4fa0f2ede865ef3f1dbbe7531aa283bbe7d86e713e5ae233fefde9ad89b58e90658ccad8d69f9"
}
],
"type": "library",
"bom-ref": "pkg:nuget/Iesi.Collections@4.0.4?sha512=8e579b4a3bf66bb6a661f297114b0f0d27f6622f6bd3f164bef4fa0f2ede865ef3f1dbbe7531aa283bbe7d86e713e5ae233fefde9ad89b58e90658ccad8d69f9"
}
분석기 동작 사용자 정의#
분석기를 사용자 정의하는 방법은 활성화 방식에 따라 다릅니다.
GitLab 분석기의 모든 사용자 정의는 기본 브랜치에 병합하기 전에 머지 리퀘스트에서 테스트합니다. 그렇게 하지 않으면 다수의 오탐을 포함해 예기치 않은 결과가 나올 수 있습니다.
CI/CD 템플릿으로 동작 사용자 정의#
사용 가능한 spec 입력#
다음 spec 입력은 Dependency-Scanning.v2.gitlab-ci.yml 템플릿과 함께 사용할 수 있습니다.
| Spec 입력 | 유형 | 기본값 | 설명 |
|---|---|---|---|
job_name |
string | "dependency-scanning" |
의존성 스캔 job의 이름. |
stage |
string | test |
의존성 스캔 job의 스테이지. |
allow_failure |
boolean | true |
의존성 스캔 job이 실패했을 때 파이프라인을 실패시킬지 여부. |
analyzer_image_prefix |
string | "$CI_TEMPLATE_REGISTRY_HOST/security-products" |
분석기 리포지터리를 가리키는 레지스트리 URL 접두사. |
analyzer_image_name |
string | "dependency-scanning" |
의존성 스캔 job이 사용하는 분석기 이미지의 리포지터리. |
analyzer_image_version |
string | "2" |
의존성 스캔 job이 사용하는 분석기 이미지의 버전. |
additional_ca_cert_bundle |
string | 신뢰할 CA 인증서 번들. 여기에 제공한 CA 번들은 시스템 인증서에 추가되며 스캔 과정의 다른 도구에서도 사용됩니다. 자세한 내용은 사용자 정의 TLS 인증 기관을 참고합니다. | |
pip_manifest_file_name_pattern |
string | 의존성 해석과 매니페스트 스캔에 사용할 사용자 정의 pip 매니페스트 파일 이름 패턴. 패턴은 디렉터리 경로가 아니라 파일 이름에만 일치해야 합니다. 구문에 대한 자세한 내용은 doublestar 라이브러리를 참고합니다. | |
pipcompile_lockfile_file_name_pattern |
string | 분석 시 사용할 사용자 정의 pip-compile 잠금 파일 이름 패턴. 패턴은 디렉터리 경로가 아니라 파일 이름에만 일치해야 합니다. 구문에 대한 자세한 내용은 doublestar 라이브러리를 참고합니다. | |
pipcompile_requirements_file_name_pattern |
string | GitLab 19.0에서 사용 중단되었습니다. 대신 pipcompile_lockfile_file_name_pattern을 사용합니다. |
|
max_scan_depth |
number | 2 |
분석기가 지원되는 파일을 검색할 디렉터리 단계 수를 정의합니다. -1 값은 깊이와 관계없이 분석기가 모든 디렉터리를 검색한다는 뜻입니다. |
excluded_paths |
string | "**/spec,**/test,**/tests,**/tmp" |
스캔에서 제외할 경로의 쉼표 구분 목록(glob 지원). |
include_dev_dependencies |
boolean | true |
지원되는 파일을 스캔할 때 개발/테스트 의존성을 포함합니다. |
enable_static_reachability |
boolean | false |
정적 도달 가능성을 활성화합니다. |
enable_manifest_fallback |
boolean | true |
매니페스트 폴백을 활성화합니다. |
analyzer_log_level |
string | "info" |
의존성 스캔의 로깅 수준. 옵션은 fatal, error, warn, info, debug입니다. |
enable_vulnerability_scan |
boolean | true |
생성된 SBOM의 취약점 분석을 활성화합니다. |
api_timeout |
number | 10 |
의존성 스캔 SBOM API 요청 제한 시간(초). |
api_scan_download_delay |
number | 3 |
스캔 결과를 다운로드하기 전 의존성 스캔 SBOM API의 초기 지연 시간(초). |
resolution_jobs_stage |
string | .pre |
의존성 해석 job의 스테이지. |
resolution_jobs_allow_failure |
boolean | true |
true이면 해석 job이 실패해도 파이프라인이 실패하지 않습니다. false이면 해석 실패가 파이프라인을 차단합니다. |
disabled_resolution_jobs |
string | "" |
비활성화할 해석 job의 쉼표 구분 목록(예: "maven, python"). 기본적으로 사용 가능한 모든 해석 job이 활성화됩니다. 가능한 값은 maven,gradle,python입니다. 의존성 해석을 참고합니다. |
resolution_jobs_checkout_timeout |
number | 60 |
해석 서비스가 리포지터리 체크아웃을 기다리는 제한 시간(초). 양의 정수여야 합니다. |
resolution_jobs_script_timeout |
number | 60 |
의존성 해석 서비스가 해석 스크립트를 생성하기를 기다리는 제한 시간(초). 양의 정수여야 합니다. 서비스가 여전히 리포지터리 체크아웃을 기다리고 있다면 대신 resolution_jobs_checkout_timeout을 늘립니다. |
maven_resolution_job_name |
string | "dependency-scanning:maven-resolution" |
Maven 의존성 해석 job의 이름. |
maven_resolution_image |
string | "registry.gitlab.com/security-products/dependency-resolution/ubi9/openjdk-21:1" |
Maven 의존성 해석 job이 사용하는 이미지. |
maven_dependency_plugin_version |
string | "3.7.0" |
Maven 의존성 해석 중 사용하는 maven-dependency-plugin의 버전. 3.7.0 이상이어야 합니다. |
python_resolution_job_name |
string | "dependency-scanning:python-resolution" |
Python 의존성 해석 job의 이름. |
python_resolution_image |
string | "registry.gitlab.com/security-products/dependency-resolution/ubi9/python-312-minimal-with-piptools-7:9" |
Python 의존성 해석 job이 사용하는 이미지. |
gradle_resolution_job_name |
string | "dependency-scanning:gradle-resolution" |
Gradle 의존성 해석 job의 이름. |
gradle_resolution_image |
string | "registry.gitlab.com/security-products/dependency-resolution/ubi9/openjdk-17-with-gradle-8:1" |
Gradle 의존성 해석 job이 사용하는 이미지. |
사용 가능한 CI/CD 변수#
이 변수들은 spec 입력을 대체할 수 있으며 베타 latest 템플릿과도 호환됩니다.
| CI/CD 변수 | 설명 |
|---|---|
AST_ENABLE_MR_PIPELINES |
의존성 스캔 job을 MR 파이프라인에서 실행할지 브랜치 파이프라인에서 실행할지 제어합니다. 기본값: "true". 프로젝트가 MR 파이프라인을 사용하지 않으면 중복 파이프라인을 피하도록 이 값을 비활성화합니다. 파이프라인 실행 정책이 주입한 job에 대해서는 의존성 스캔의 머지 리퀘스트 파이프라인 비활성화를 참고합니다. |
ADDITIONAL_CA_CERT_BUNDLE |
신뢰할 CA 인증서 번들. 여기에 제공한 CA 번들은 시스템 인증서에 추가되며 스캔 과정의 다른 도구에서도 사용됩니다. 자세한 내용은 사용자 정의 TLS 인증 기관을 참고합니다. |
ANALYZER_ARTIFACT_DIR |
CycloneDX 보고서(SBOM)가 저장되는 디렉터리. 기본값: ${CI_PROJECT_DIR}/sca-artifacts. |
DEPENDENCY_SCANNING_DISABLED |
"true" 또는 "1"로 설정하면 모든 의존성 스캔 job을 비활성화합니다. 기본값: 설정되지 않음. |
DS_EXCLUDED_ANALYZERS |
의존성 스캔에서 제외할 분석기를 이름으로 지정합니다. |
DS_EXCLUDED_PATHS |
경로를 기준으로 스캔에서 파일과 디렉터리를 제외합니다. 쉼표로 구분한 패턴 목록입니다. 패턴은 glob(지원되는 패턴은 doublestar.Match 참고) 또는 파일이나 폴더 경로(예: doc,spec)일 수 있습니다. 일치 규칙은 스캔에서 경로 제외를 참고합니다. 스캔이 실행되기 전에 적용되는 사전 필터입니다. 의존성 탐지와 정적 도달 가능성 모두에 적용됩니다. 기본값: "**/spec,**/test,**/tests,**/tmp,**/node_modules,**/.bundle,**/vendor,**/.git". |
DS_MAX_DEPTH |
분석기가 스캔할 지원 파일을 검색할 디렉터리 깊이를 정의합니다. -1 값은 깊이와 관계없이 모든 디렉터리를 스캔합니다. 기본값: 2. |
DS_INCLUDE_DEV_DEPENDENCIES |
"false"로 설정하면 개발 의존성을 보고하지 않습니다. Composer, Conda, Gradle, Maven, npm, pnpm, Pipenv, Poetry, uv를 사용하는 프로젝트만 지원됩니다. 기본값: "true" |
DS_PIP_MANIFEST_FILE_NAME_PATTERN |
의존성 해석과 매니페스트 스캔에서 처리할 pip 매니페스트 파일을 glob 패턴 일치로 정의합니다(예: custom-requirements.txt 또는 *-requirements.txt). 패턴은 디렉터리 경로가 아니라 파일 이름에만 일치해야 합니다. 구문에 대한 자세한 내용은 glob 패턴 문서를 참고합니다. |
PIP_REQUIREMENTS_FILE |
GitLab 19.0에서 사용 중단되었습니다. 대신 DS_PIP_MANIFEST_FILE_NAME_PATTERN을 사용합니다. |
DS_PIPCOMPILE_LOCKFILE_FILE_NAME_PATTERN |
처리할 pip-compile 잠금 파일을 glob 패턴 일치로 정의합니다(예: requirements*.txt 또는 *-requirements.txt). 패턴은 디렉터리 경로가 아니라 파일 이름에만 일치해야 합니다. 구문에 대한 자세한 내용은 glob 패턴 문서를 참고합니다. |
DS_PIPCOMPILE_REQUIREMENTS_FILE_NAME_PATTERN |
GitLab 19.0에서 사용 중단되었습니다. 대신 DS_PIPCOMPILE_LOCKFILE_FILE_NAME_PATTERN을 사용합니다. |
SECURE_ANALYZERS_PREFIX |
공식 기본 이미지를 제공하는 Docker 레지스트리(프록시)의 이름을 재정의합니다. |
DS_FF_LINK_COMPONENTS_TO_GIT_FILES |
의존성 목록의 컴포넌트를 CI/CD 파이프라인에서 동적으로 생성된 잠금 파일과 그래프 파일이 아니라 리포지터리에 커밋된 파일에 연결합니다. 이렇게 하면 모든 컴포넌트가 리포지터리의 소스 파일에 연결됩니다. 기본값: "false". |
SEARCH_IGNORE_HIDDEN_DIRS |
숨김 디렉터리를 무시합니다. 의존성 스캔과 정적 도달 가능성 모두에 적용됩니다. 기본값: "true". |
DS_STATIC_REACHABILITY_ENABLED |
정적 도달 가능성을 활성화합니다. 기본값: "false". |
DS_ENABLE_VULNERABILITY_SCAN |
생성된 SBOM 파일의 취약점 스캔을 활성화합니다. 의존성 스캔 보고서를 생성합니다. 기본값: "true". |
DS_API_TIMEOUT |
의존성 스캔 SBOM API 요청 제한 시간(초)(최소: 5, 최대: 300). 기본값: 10 |
DS_API_SCAN_DOWNLOAD_DELAY |
스캔 결과를 다운로드하기 전의 초기 지연 시간(초)(최소: 1, 최대: 120). 기본값: 3 |
DS_ENABLE_MANIFEST_FALLBACK |
잠금 파일이나 의존성 그래프 내보내기가 없을 때 매니페스트 폴백을 활성화합니다. 매니페스트 폴백을 참고합니다. "false"로 설정하면 매니페스트 파일은 있지만 잠금 파일이나 의존성 그래프 내보내기가 없는 디렉터리가 있을 때 분석기가 0이 아닌 상태로 종료하며 영향을 받은 각 매니페스트의 이름을 표시합니다. 기본값: "true". |
DS_SKIP_IF_NO_SUPPORTED_FILES |
"true"로 설정하면 프로젝트에서 지원되는 파일이 탐지되지 않을 때 의존성 스캔 job을 건너뜁니다. 자세한 내용은 지원되는 파일이 없을 때 job 건너뛰기를 참고합니다. 기본값: "false". |
SECURE_LOG_LEVEL |
로그 수준. 기본값: "info". |
DS_DISABLED_RESOLUTION_JOBS |
비활성화할 해석 job의 쉼표 구분 목록(예: "maven, python"). 기본적으로 사용 가능한 모든 해석 job이 활성화됩니다. 가능한 값은 maven,gradle,python입니다. |
DS_MAVEN_RESOLUTION_IMAGE |
Maven 의존성 해석 job이 사용하는 이미지. |
DS_MAVEN_DEPENDENCY_PLUGIN_VERSION |
Maven 의존성 해석 중 사용하는 maven-dependency-plugin의 버전. 3.7.0 이상이어야 합니다. 기본값: 3.7.0. |
MAVEN_ARGS |
Maven 의존성 해석 중 mvn 명령에 전달할 추가 인수. 기존 MAVEN_CLI_OPTS 변수를 대체합니다. |
DS_PYTHON_RESOLUTION_IMAGE |
Python 의존성 해석 job이 사용하는 이미지. |
PIP_INDEX_URL |
Python 의존성 해석 중 사용하는 Python 패키지 인덱스의 기본 URL. 기본값: https://pypi.org/simple. |
PIP_EXTRA_INDEX_URL |
Python 의존성 해석 중 PIP_INDEX_URL과 함께 사용할 추가 Python 패키지 인덱스 URL. |
DS_GRADLE_RESOLUTION_IMAGE |
Gradle 의존성 해석 job이 사용하는 이미지. |
GRADLE_CLI_OPTS |
Gradle 의존성 해석 중 gradle 또는 gradlew 명령에 전달할 추가 인수. |
의존성 스캔의 머지 리퀘스트 파이프라인 비활성화#
기본적으로 Dependency-Scanning.v2.gitlab-ci.yml 템플릿은 머지 리퀘스트 파이프라인에서
의존성 스캔 job을 실행합니다. 프로젝트가 다른 job에 머지 리퀘스트 파이프라인을 사용하지 않으면
머지 리퀘스트마다 파이프라인이 두 개 실행될 수 있으며, 다른 job은 별도의 브랜치
파이프라인에서 실행됩니다. 이 동작을 비활성화하려면 CI/CD
변수 AST_ENABLE_MR_PIPELINES: "false"를 설정합니다.
템플릿이 파이프라인 실행 정책으로 주입되는 경우,
프로젝트나 그룹 설정 대신 정책의 CI/CD 구성에서 AST_ENABLE_MR_PIPELINES를 설정합니다. 파이프라인 실행 정책은
기본적으로 격리되어 실행되며 variables_override가 허용하지 않는 한 프로젝트나 그룹 설정의
변수를 적용하지 않습니다. 정책에서 설정하지 않은 변수는
기본값이 "true"이므로, 명시적으로 설정하지 않으면 job이 머지 리퀘스트 파이프라인에서 실행됩니다.
프로젝트의 workflow:rules 구성도 이 동작을 막지 못합니다.
정책이 적용되는 모든 프로젝트에서 job을 브랜치 파이프라인으로 실행하려면 정책 CI/CD 구성에서 변수를 설정합니다.
variables:
AST_ENABLE_MR_PIPELINES: "false"
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
프로젝트나 그룹의 값을 대신 사용하려면 파이프라인 실행 정책의 변수를 참고합니다.
지원되는 파일이 없을 때 job 건너뛰기#
기본적으로 의존성 스캔 job은 프로젝트에 지원되는 파일이 없더라도
템플릿을 포함하는 모든 파이프라인에서 실행됩니다. 지원되는 파일이 탐지되지 않을 때
job을 건너뛰려면 DS_SKIP_IF_NO_SUPPORTED_FILES를 "true"로 설정합니다.
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
variables:
DS_SKIP_IF_NO_SUPPORTED_FILES: "true"
이 변수를 설정하면 프로젝트에 지원되는 파일 목록의 파일이 하나 이상 있거나,
DS_PIPCOMPILE_LOCKFILE_FILE_NAME_PATTERN, DS_PIP_MANIFEST_FILE_NAME_PATTERN 또는
PIP_REQUIREMENTS_FILE(사용 중단됨)로 사용자 정의 패턴을 설정한 경우에만 의존성 스캔 job이 실행됩니다.
사용자 정의 TLS 인증 기관#
의존성 스캔은 분석기 컨테이너 이미지에 포함된 기본 인증서 대신 SSL/TLS 연결에 사용자 정의 TLS 인증서를 사용할 수 있습니다.
사용자 정의 TLS 인증 기관 사용#
사용자 정의 TLS 인증 기관을 사용하려면
X.509 PEM 공개 키 인증서의 텍스트 표현을
CI/CD 변수 ADDITIONAL_CA_CERT_BUNDLE에 할당합니다.
예를 들어 .gitlab-ci.yml 파일에서 인증서를 구성하려면 다음과 같이 합니다.
variables:
ADDITIONAL_CA_CERT_BUNDLE: |
-----BEGIN CERTIFICATE-----
MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
...
jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
-----END CERTIFICATE-----
의존성 해석#
히스토리
프로젝트의 리포지터리에 지원되는 잠금 파일이나 의존성 그래프 내보내기가 커밋되어 있지 않으면, 의존성 해석이 스캔 실행 전에 필요한 파일을 자동으로 생성할 수 있습니다.
의존성 해석은 프로젝트에서 지원되는 매니페스트 파일이 탐지되면 자동으로 실행됩니다.
해석 job은 최소한의 에코시스템 이미지(예: ubi9/openjdk-21)를 사용해 .pre 스테이지에서 실행되며,
잠금 파일이나 의존성 그래프 내보내기를 네이티브 방식으로 생성합니다. 이 job은 기존 잠금 파일이나
그래프 내보내기를 보존하고 없을 때만 새로 생성합니다. 생성된 아티팩트는 이후 test 스테이지의
dependency-scanning job이 사용합니다. 기본 이미지를 동등한 대체 이미지
(예: eclipse-temurin:jdk-21)나 필요한 빌드 도구가 들어 있는 사용자 정의 이미지로 바꿀 수 있습니다.
다음 에코시스템이 의존성 해석을 지원합니다.
| 언어 | 패키지 매니저 | 탐지되는 매니페스트 파일 | 해석 명령 | 출력 아티팩트 |
|---|---|---|---|---|
| Java | Maven | pom.xml |
mvn dependency:tree |
maven.graph.json |
| Java/Kotlin | Gradle | build.gradle, build.gradle.kts |
gradle dependencies |
gradle.graph.txt |
| Python | pip, setuptools | requirements.txt, requirements.in, requirements.pip, requires.txt, setup.py, setup.cfg, pyproject.toml(Poetry 제외) |
pip-compile |
pipcompile.lock.txt |
의존성 해석 사용자 정의#
사용 가능한 모든 옵션은 사용 가능한 spec 입력과 사용 가능한 CI/CD 변수를 참고합니다.
사용자 정의 의존성 해석 이미지 사용#
직접 만든 이미지를 사용하려면 다음 입력을 설정할 수 있습니다.
maven_resolution_imagegradle_resolution_imagepython_resolution_image
예를 들어 maven 해석에 사용자 정의 이미지를 사용하려면 다음과 같이 합니다.
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
inputs:
maven_resolution_image: "registry.gitlab.mycorp.com/eclipse-temurin:jdk-21"
또는 다음 CI/CD 변수를 설정할 수 있습니다.
DS_MAVEN_RESOLUTION_IMAGEDS_GRADLE_RESOLUTION_IMAGEDS_PYTHON_RESOLUTION_IMAGE
의존성 해석 비활성화#
특정 에코시스템의 의존성 해석을 비활성화하려면
DS_DISABLED_RESOLUTION_JOBS CI/CD 변수 또는 disabled_resolution_jobs 입력을 사용합니다.
가능한 값은 maven,gradle,python입니다.
예를 들어 maven의 의존성 해석을 비활성화하려면 다음과 같이 합니다.
variables:
DS_DISABLED_RESOLUTION_JOBS: "maven"
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
의존성 해석의 보안 고려 사항#
의존성 해석 job은 CI/CD job 컨테이너에서 에코시스템 네이티브 빌드 도구(mvn, gradle,
pip-compile)를 실행합니다. 이 도구들은 시작 시 확장 기능을 로드하거나
임의의 코드를 실행할 수 있는 환경 변수와 구성 파일을 네이티브 방식으로 따르며,
다음이 포함됩니다.
- Maven:
MAVEN_ARGS,MAVEN_CLI_OPTS(레거시),MAVEN_OPTS,JAVA_TOOL_OPTIONS,-s또는--settings로 참조되는 모든settings.xml,pom.xml또는settings.xml에 선언된<extensions>. - Gradle:
GRADLE_OPTS,JAVA_TOOL_OPTIONS,--init-script, 그리고build.gradle또는build.gradle.kts의 최상위 Groovy 또는 Kotlin 코드. - Python:
PIP_INDEX_URL,PIP_EXTRA_INDEX_URL,setup.py, 그리고 잠금 파일 설치 훅.
이러한 CI/CD 변수를 설정하거나 프로젝트의 빌드
파일을 수정할 수 있는 사람은 누구나 해석 job에서 임의의 코드가 실행되게 할 수 있습니다. 해석
job은 CI_JOB_TOKEN으로 실행되고, 범위 내의 마스킹된 CI/CD 변수에 접근하며,
job이 실행되는 동안 프로젝트 리포지터리를 읽거나 씁니다.
이 특성은 에코시스템 네이티브 빌드 도구에 내재된 것이며 의존성 스캔에만 해당하지 않습니다. 해석 job을 민감한 실행 컨텍스트로 취급합니다.
권장 통제 방법은 다음과 같습니다.
- 앞에서 나열한 변수를 정의하거나 재정의할 수 있는 사람을 제한합니다.
보호된 브랜치와 태그로 범위를 한정한 보호된 CI/CD 변수를
사용합니다. 어떤 개발자든 편집할 수 있는
.gitlab-ci.yml의variables:블록에는 설정하지 않습니다. MAVEN_ARGS,MAVEN_CLI_OPTS,GRADLE_OPTS,--init-script, 사용자 정의settings.xml,pom.xml의<extensions>사용을 표준 코드 리뷰 과정의 일부로 감사합니다.- 스캔 실행 정책으로
의존성 스캔을 강제하면 대상 프로젝트에서 개발자가 작성한
variables:가 주입된 해석 job으로 전달됩니다. 정책 프레임워크가 전달하는 변수를 검토하고, 정책에서 빌드 도구 변수를 설정 해제하거나 재정의합니다. - 프로젝트의 빌드가 직접 관리하고 신뢰하는 CI/CD job(예:
mvn package를 실행하는build스테이지)에서 실행된다면, 같은 job에서 잠금 파일 또는 의존성 그래프 내보내기를 생성하고 GitLab이 제공하는 해석 job을DS_DISABLED_RESOLUTION_JOBS로 비활성화합니다. 이 방식은 빌드 도구를 실행하는 위험을 줄이지는 않지만, 민감한 job 컨텍스트를 하나로 제한합니다. - 알려진 툴체인을 보장해야 한다면 다이제스트로 고정한 사용자 정의 해석 이미지를 사용합니다.
의존성 해석 제한 사항#
의존성 해석은 에코시스템당 고정된 단일 런타임 버전과 빌드 도구를 갖춘 기본 이미지 또는 사용자 정의 이미지에서 에코시스템 네이티브 빌드 도구를 실행합니다.
해석 성공 여부는 프로젝트가 이 환경과 호환되는지, 패키지 레지스트리에 접근할 수 있는지, 그리고 의존성 수집 범위를 넘어서는 빌드 시점 요구 사항이 없는지에 달려 있습니다.
기본 환경에서 실패하는 프로젝트는 해당 해석 job 이미지를 재정의하여 필요한 모든 의존성을 갖춘 호환 이미지를 제공할 수 있습니다.
호환되더라도 해석 환경이 프로젝트가 빌드된 정확한 런타임 버전이나 기타 요구 사항과 일치하지 않을 수 있습니다. 따라서 생성된 의존성 그래프가 프로젝트의 실제 빌드 환경에서 해석될 정확한 의존성 집합을 반영하지 않을 수 있습니다. 고정된 런타임 버전, 해석되지 않은 환경 마커, 플랫폼별 의존성, 해석 job에서 사용할 수 없는 빌드 시점 컨텍스트에 좌우되는 조건부 의존성 그룹이 차이의 원인이 될 수 있습니다.
의존성 해석 워크플로로 충분히 다루지 못하는 고도로 맞춤화된 빌드가 있는 프로젝트라면, 직접 빌드 환경에서 생성한 잠금 파일이나 의존성 그래프 내보내기를 제공해야 합니다. 자세한 내용은 잠금 파일 또는 의존성 그래프 내보내기 수동 생성을 참고합니다.
Maven 해석 알려진 문제#
기본 환경: Java 21, Maven 3.9
Maven 프로젝트에는 다음 제한 사항이 적용됩니다.
- Maven enforcer 플러그인: Maven Enforcer Plugin에서 엄격한 Java 버전 규칙을 사용하는 프로젝트는 실패할 수 있습니다. 해석 명령은 이를 완화하기 위해
-Denforcer.skip=true를 전달하지만 모든 enforcer 규칙이 건너뛰어지는 것은 아닙니다. - 프로파일 기반 활성화: JDK 버전으로 활성화되는 조건부 모듈(예: ZXing, Dubbo)을 사용하는 프로젝트는 원래 대상으로 한 Java 버전으로 빌드할 때와 다른 의존성 그래프를 생성할 수 있습니다.
- 초기 수명 주기 단계의 플러그인: validate 또는 initialize 단계에 바인딩된 플러그인이 해석 이미지의 Java 버전과 호환되지 않으면 실패가 발생할 수 있습니다.
Gradle 해석 알려진 문제#
기본 환경: Java 17, Gradle 8
해석 job은 Gradle 래퍼가 있으면 ./gradlew dependencies를, 없으면 gradle dependencies를
실행합니다. 다중 모듈 프로젝트에서는 각 서브프로젝트를 :<subproject>:dependencies로 개별적으로 해석합니다.
job은 출력을 해당 프로젝트 디렉터리의 gradle.graph.txt에 기록합니다.
Gradle 프로젝트에는 다음 제한 사항이 적용됩니다.
- 래퍼 요구 사항: Gradle 래퍼(
gradlew)가 있으면 유효한gradle-wrapper.jar를 참조해야 합니다. 래퍼가 없으면 job은 시스템의gradle을 사용합니다. - 플러그인 및 버전 호환성: 특정 Gradle 플러그인, 사용자 정의 툴체인 또는 Java 17이 아닌 Java 버전이 필요한 프로젝트는 실패할 수 있습니다. 필요한 빌드 환경이 들어 있는 이미지로 해석 이미지(
spec:inputs:gradle_resolution_image)를 재정의합니다.
Python 해석 알려진 문제#
기본 환경: Python 3.12, pip-tools 7
Python 프로젝트에는 다음 제한 사항이 적용됩니다.
- Pipfile 미지원: Pipfile 프로젝트(
Pipfile.lock파일이 없는 경우)는 지원되지 않습니다. 리포지터리에Pipfile파일이 있어도 Python 해석 job은 트리거되지 않습니다. - Git/VCS 의존성: Git 또는 VCS URL(
git+https://...)로 지정된 의존성은 해석할 수 없습니다. 해석 명령은 해당 매니페스트 파일에서는 실패하지만 다른 파일이 있으면 계속 처리합니다. - 로컬/편집 가능 설치:
-e .,file:또는 로컬 경로 참조를 사용하는 항목은 해석 전에 제거되며 경고가 출력됩니다. 해당 패키지는 출력에 나타나지 않습니다. - 동적
install_requires가 있는setup.py:install_requires가 런타임에 파일에서 값을 읽으면 경고가 출력되며pip-compile이 해석을 시도하지만 실패할 수 있습니다. [project]테이블이 없는pyproject.toml: 빌드 시스템 구성만 포함한pyproject.toml은 건너뛰며 경고가 출력됩니다.DS_INCLUDE_DEV_DEPENDENCIES범위: 개발 의존성 포함은[dependency-groups]가 있는pyproject.toml에만 구현되어 있습니다.
잠금 파일 또는 의존성 그래프 내보내기 수동 생성#
프로젝트의 리포지터리에 지원되는 잠금 파일이나 의존성 그래프 내보내기가 커밋되어 있지 않고 의존성 해석도 이를 지원하지 않는다면 직접 제공해야 합니다.
빌드가 복잡하거나, 사용자 정의 빌드 단계, 프라이빗 레지스트리 또는 특정 환경 요구 사항이 있는 프로젝트라면 잠금 파일이나 의존성 그래프 내보내기를 수동으로 생성하는 방법을 고려합니다. 기존 빌드 과정에서 파일을 생성하는 편이 그 환경을 재현하도록 의존성 해석을 구성하는 것보다 대개 빠르고 간단합니다. 수동 생성은 더 정확한 결과도 냅니다. 파일에는 전이 의존성과 플랫폼별 해석을 포함해 직접 수행한 빌드의 정확한 의존성 버전이 반영됩니다.
아래 예시는 널리 쓰이는 언어와 패키지 관리자에 대해 GitLab 분석기가 지원하는 파일을 생성하는 방법을 보여 줍니다. 전체 목록은 지원되는 언어 및 파일도 참고합니다.
Go#
이 방법은 Go 툴체인의 go mod graph 명령을 사용해
직접 의존성과 전이 의존성을 포함하여 분석기에 필요한 모든 정보가 담긴 go.graph 파일을 생성합니다.
이 파일이 없으면 분석기는 go.mod만으로 컴포넌트를 추출하지만
의존성 경로 정보를 사용할 수 없고,
같은 모듈의 여러 버전이 존재하면
오탐이 발생할 수 있습니다.
Go 프로젝트에서 분석기를 활성화하려면 다음과 같이 합니다.
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.- 프로젝트의 기존 빌드 job에
go mod graph명령을 추가하거나, 빌드 job이 없으면 전용 job을 만듭니다. 스캔이 시작될 때 아티팩트를 사용할 수 있도록 이 job은dependency-scanningjob보다 먼저 실행되어야 합니다. go.graph를 job 아티팩트로 선언합니다.
기존 빌드 job에 명령을 추가하면 빌드의 모듈 캐시를 재사용하므로 별도의 job에서 실행하는 것보다 빠릅니다.
예를 들면 다음과 같습니다.
stages:
- build
- test
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
build:
# Running in the build stage ensures that the dependency-scanning job
# receives the go.graph artifact.
stage: build
image: "golang:latest"
script:
# Your regular build script
- go mod tidy
- go build ./...
# New instruction to generate the dependency graph
- go mod graph > go.graph
# Make the artifact available to the dependency-scanning job.
artifacts:
paths:
- "**/go.graph"
Gradle#
Gradle 프로젝트에서는 다음 방법 중 하나로 의존성 그래프 내보내기를 생성합니다.
- Gradle
dependencies태스크 - Nebula Gradle Dependency Lock Plugin
- Gradle
HtmlDependencyReportTask
Gradle dependencies 태스크#
이 방법은 자동
의존성 해석을 구동하는 것과 같은 gradle dependencies 태스크를 사용합니다. 이 방식을 권장하는 이유는
직접 의존성과 전이 의존성, 그리고 의존성 경로를
활성화하는 그래프 정보를 포함해 분석기에 필요한 모든 정보가 담긴 단일 gradle.graph.txt 파일을
생성하기 때문입니다.
Gradle 프로젝트에서 분석기를 활성화하려면 다음과 같이 합니다.
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.- 프로젝트의 기존 빌드 job에
gradle dependencies명령을 추가하거나, 빌드 job이 없으면 전용 job을 만듭니다. 스캔이 시작될 때 아티팩트를 사용할 수 있도록 이 job은dependency-scanningjob보다 먼저 실행되어야 합니다. gradle.graph.txt를 job 아티팩트로 선언합니다.DS_DISABLED_RESOLUTION_JOBSCI/CD 변수 또는disabled_resolution_jobs입력 값에gradle을 추가하여 자동 의존성 해석을 비활성화합니다.
기존 빌드 job에 명령을 추가하면 빌드의 Gradle 데몬, 캐시, 해석된 구성을 재사용하므로 별도의 job에서 실행하는 것보다 빠릅니다.
예를 들면 다음과 같습니다.
stages:
- build
- test
image: gradle:8.0-jdk11
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
build:
# Running in the build stage ensures that the dependency-scanning job
# receives the gradle.graph.txt artifact.
stage: build
script:
# Your regular build script
- ./gradlew build
# New instruction to generate the dependency graph
- ./gradlew dependencies > gradle.graph.txt
# Make the artifact available to the dependency-scanning job.
artifacts:
paths:
- "**/gradle.graph.txt"
의존성 잠금 플러그인#
gradle-dependency-lock-plugin은 Gradle 9 이상과 호환되지 않습니다. 해당 버전으로
dependencies.lock 파일을 생성하려고 하면, 플러그인이 Gradle 9에서 제거된 내부 Gradle API에
의존하기 때문에 빌드가 실패합니다. Gradle 9 이상 프로젝트에서는
Gradle dependencies 태스크 또는
HtmlDependencyReportTask를 대신 사용합니다.
이 방법은 gradle-dependency-lock-plugin을 사용해
dependencies.lock(직접 의존성과 전이 의존성)과
dependencies.direct.lock(직접 의존성만) 두 개의 잠금 파일을 생성합니다. 분석기는 두 파일을 함께 사용해
의존성 그래프에서 직접 의존성과 전이 의존성을 구분합니다.
Gradle 프로젝트에서 분석기를 활성화하려면 다음과 같이 합니다.
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.build.gradle또는build.gradle.kts를 편집하거나init스크립트를 사용하여 프로젝트에 gradle-dependency-lock-plugin을 적용합니다.- 프로젝트의 기존 빌드 job에
generateLock saveLock명령을 추가하거나, 빌드 job이 없으면 전용 job을 만듭니다. 스캔이 시작될 때 아티팩트를 사용할 수 있도록 이 job은dependency-scanningjob보다 먼저 실행되어야 합니다. dependencies.lock과dependencies.direct.lock을 job 아티팩트로 선언합니다.DS_DISABLED_RESOLUTION_JOBSCI/CD 변수 또는disabled_resolution_jobs입력 값에gradle을 추가하여 자동 의존성 해석을 비활성화합니다.
예를 들면 다음과 같습니다.
stages:
- build
- test
image: gradle:8.0-jdk11
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
generate nebula lockfile:
# Running in the build stage ensures that the dependency-scanning job
# receives the scannable artifacts.
stage: build
script:
- |
cat << EOF > nebula.gradle
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:12.7.1'
}
}
allprojects {
apply plugin: nebula.plugin.dependencylock.DependencyLockPlugin
}
EOF
./gradlew --init-script nebula.gradle -PdependencyLock.includeTransitives=true -PdependencyLock.lockFile=dependencies.lock generateLock saveLock
./gradlew --init-script nebula.gradle -PdependencyLock.includeTransitives=false -PdependencyLock.lockFile=dependencies.direct.lock generateLock saveLock
# generateLock saves the lockfile in the build/ directory of a project
# and saveLock copies it into the root of a project. To avoid duplicates
# and get an accurate location of the dependency, use find to remove the
# lockfiles in the build/ directory only.
after_script:
- find . -path '*/build/dependencies*.lock' -print -delete
# Make the artifacts available to the dependency-scanning job.
artifacts:
paths:
- '**/dependencies*.lock'
HtmlDependencyReportTask#
이 방법은
HtmlDependencyReportTask를
사용해 직접 의존성과 전이 의존성이 담긴 gradle-html-dependency-report.js 파일을
생성합니다. 이 방법은 Gradle 버전 4부터 8까지에서 테스트되었으며
Gradle 9 이상 프로젝트에 권장됩니다.
Gradle 프로젝트에서 분석기를 활성화하려면 다음과 같이 합니다.
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.- 프로젝트의 기존 빌드 job에
gradle htmlDependencyReport명령을 추가하거나, 빌드 job이 없으면 전용 job을 만듭니다. 스캔이 시작될 때 아티팩트를 사용할 수 있도록 이 job은dependency-scanningjob보다 먼저 실행되어야 합니다. gradle-html-dependency-report.js를 job 아티팩트로 선언합니다.DS_DISABLED_RESOLUTION_JOBSCI/CD 변수 또는disabled_resolution_jobs입력 값에gradle을 추가하여 자동 의존성 해석을 비활성화합니다.
예를 들면 다음과 같습니다.
stages:
- build
- test
# Define the image that contains Java and Gradle
image: gradle:8.0-jdk11
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
build:
stage: build
script:
- gradle --init-script report.gradle htmlDependencyReport
# The gradle task writes the dependency report as a javascript file under
# build/reports/project/dependencies. Because the file has an un-standardized
# name, the after_script finds and renames the file to
# `gradle-html-dependency-report.js` copying it to the same directory as
# `build.gradle`
after_script:
- |
reports_dir=build/reports/project/dependencies
while IFS= read -r -d '' src; do
dest="${src%%/$reports_dir/*}/gradle-html-dependency-report.js"
cp $src $dest
done < <(find . -type f -path "*/${reports_dir}/*.js" -not -path "*/${reports_dir}/js/*" -print0)
# Make the artifact available to the dependency-scanning job.
artifacts:
paths:
- "**/gradle-html-dependency-report.js"
위 명령은 report.gradle 파일을 사용하며, 이 파일은 --init-script로 제공하거나 그 내용을 build.gradle에 직접 추가할 수 있습니다.
allprojects {
apply plugin: 'project-report'
}
의존성 보고서에 일부 구성의 의존성이 해석되지 못해 FAILED로 표시될 수 있습니다.
이 경우 의존성 스캔은 경고를 기록하지만 job을 실패시키지는 않습니다. 해석 실패가 보고될 때
파이프라인이 실패하기를 원한다면, 위의 build 예시에
다음 추가 단계를 더합니다.
while IFS= read -r -d '' file; do
grep --quiet -E '"resolvable":\s*"FAILED' $file && echo "Dependency report has dependencies with FAILED resolution status" && exit 1
done < <(find . -type f -path "*/gradle-html-dependency-report.js -print0)
Maven#
이 방법은 자동
의존성 해석을 구동하는 것과 같은 mvn dependency:tree 명령을 사용합니다. 직접 의존성과 전이 의존성,
그리고 의존성 경로를 활성화하는 그래프 정보를 포함해
분석기에 필요한 모든 정보가 담긴 단일 maven.graph.json 파일을 생성합니다.
Maven 프로젝트에서 분석기를 활성화하려면 다음과 같이 합니다.
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.- 프로젝트의 기존 빌드 job에
mvn dependency:tree명령(maven-dependency-plugin버전3.7.0이상 사용)을 추가하거나, 빌드 job이 없으면 전용 job을 만듭니다. 스캔이 시작될 때 아티팩트를 사용할 수 있도록 이 job은dependency-scanningjob보다 먼저 실행되어야 합니다. maven.graph.json을 job 아티팩트로 선언합니다.DS_DISABLED_RESOLUTION_JOBSCI/CD 변수 또는disabled_resolution_jobs입력 값에maven을 추가하여 자동 의존성 해석을 비활성화합니다.
기존 빌드 job에 명령을 추가하면 빌드의 Maven 세션과 해석된 구성을 재사용하므로 별도의 job에서 실행하는 것보다 빠릅니다.
예를 들면 다음과 같습니다.
stages:
- build
- test
image: maven:3.9.9-eclipse-temurin-21
variables:
# Disable the automatic Maven resolution job. The dependency graph is
# generated manually in the build job below. The built-in resolution
# job which runs whenever a `pom.xml` is present is redundant.
# Alternatively, set the `disabled_resolution_jobs: "maven"` input on the
# template include.
DS_DISABLED_RESOLUTION_JOBS: "maven"
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
build:
# Running in the build stage ensures that the dependency-scanning job
# receives the maven.graph.json artifacts.
stage: build
script:
# Your regular build script
- mvn install
# New instruction to generate the dependency graph
- mvn org.apache.maven.plugins:maven-dependency-plugin:3.8.1:tree -DoutputType=json -DoutputFile=maven.graph.json
# Make the artifact available to the dependency-scanning job.
artifacts:
paths:
- "**/*.jar"
- "**/maven.graph.json"
pip#
pip 프로젝트에서는 다음 방법 중 하나로 의존성 그래프 내보내기를 생성합니다.
pip-compilepipdeptree
pip-compile#
이 방법은 자동 의존성 해석을 구동하는
pip-compile 명령을 사용합니다.
직접 의존성과 전이 의존성, 그리고 의존성 경로를
활성화하는 그래프 정보를 포함해 분석기에 필요한 모든 정보가 담긴
requirements.txt 잠금 파일을 생성합니다.
pip 프로젝트에서 분석기를 활성화하려면 다음과 같이 합니다.
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.- 프로젝트의 기존 빌드 job에
pip-compile명령을 추가하거나, 빌드 job이 없으면 전용 job을 만듭니다. 스캔이 시작될 때 아티팩트를 사용할 수 있도록 이 job은dependency-scanningjob보다 먼저 실행되어야 합니다. requirements.txt를 job 아티팩트로 선언합니다.DS_DISABLED_RESOLUTION_JOBSCI/CD 변수 또는disabled_resolution_jobs입력 값에python을 추가하여 자동 의존성 해석을 비활성화합니다.
기존 빌드 job에 명령을 추가하면 빌드에서 설치된 의존성을 재사용하므로 별도의 job에서 실행하는 것보다 빠릅니다.
예를 들면 다음과 같습니다.
stages:
- build
- test
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
build:
# Running in the build stage ensures that the dependency-scanning job
# receives the requirements.txt artifact.
stage: build
image: "python:latest"
script:
# Your regular build script
- pip install pip-tools
# New instruction to generate the dependency lockfile
- pip-compile requirements.in
# Make the artifact available to the dependency-scanning job.
artifacts:
paths:
- "**/requirements.txt"
pipdeptree#
이 방법은 pipdeptree --json을 사용해
직접 의존성과 전이 의존성, 그리고
의존성 경로를 활성화하는 그래프 정보를 포함해 분석기에 필요한 모든 정보가 담긴
pipdeptree.json 파일을 생성합니다.
pip 프로젝트에서 분석기를 활성화하려면 다음과 같이 합니다.
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.- 프로젝트의 기존 빌드 job에
pipdeptree --json명령을 추가하거나, 빌드 job이 없으면 전용 job을 만듭니다. 스캔이 시작될 때 아티팩트를 사용할 수 있도록 이 job은dependency-scanningjob보다 먼저 실행되어야 합니다. pipdeptree.json을 job 아티팩트로 선언합니다.DS_DISABLED_RESOLUTION_JOBSCI/CD 변수 또는disabled_resolution_jobs입력 값에python을 추가하여 자동 의존성 해석을 비활성화합니다.
기존 빌드 job에 명령을 추가하면 빌드에서 설치된 의존성을 재사용하므로 별도의 job에서 실행하는 것보다 빠릅니다.
예를 들면 다음과 같습니다.
stages:
- build
- test
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
build:
# Running in the build stage ensures that the dependency-scanning job
# receives the pipdeptree.json artifact.
stage: build
image: "python:latest"
script:
# Your regular build script
- pip install -r requirements.txt
# New instructions to generate the dependency graph.
# Exclude pipdeptree itself to avoid false positives.
- pip install pipdeptree
- pipdeptree -e pipdeptree --json > pipdeptree.json
# Make the artifact available to the dependency-scanning job.
artifacts:
paths:
- "**/pipdeptree.json"
알려진 문제 때문에 pipdeptree는
선택적 의존성을
상위 패키지의 의존성으로 표시하지 않습니다. 그 결과 의존성 스캔은 이를 전이 의존성이 아니라
프로젝트의 직접 의존성으로 표시합니다.
Pipenv#
이 방법은 pipenv graph 명령을 사용해
직접 의존성과 전이 의존성을 포함하여 분석기에 필요한 정보가 담긴 pipenv.graph.json 파일을
생성합니다. 이 파일이 없으면 분석기는 Pipfile.lock만으로
컴포넌트를 추출하지만 의존성 경로
정보를 사용할 수 없습니다.
Pipenv 프로젝트에서 분석기를 활성화하려면 다음과 같이 합니다.
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.- 프로젝트의 기존 빌드 job에
pipenv graph --json-tree명령을 추가하거나, 빌드 job이 없으면 전용 job을 만듭니다. 스캔이 시작될 때 아티팩트를 사용할 수 있도록 이 job은dependency-scanningjob보다 먼저 실행되어야 합니다. pipenv.graph.json을 job 아티팩트로 선언합니다.
기존 빌드 job에 명령을 추가하면 빌드에서 설치된 의존성을 재사용하므로 별도의 job에서 실행하는 것보다 빠릅니다.
예를 들면 다음과 같습니다.
stages:
- build
- test
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
build:
# Running in the build stage ensures that the dependency-scanning job
# receives the pipenv.graph.json artifact.
stage: build
image: "python:3.12"
script:
# Your regular build script
- pip install pipenv
- pipenv install
# New instruction to generate the dependency graph
- pipenv graph --json-tree > pipenv.graph.json
# Make the artifact available to the dependency-scanning job.
artifacts:
paths:
- "**/pipenv.graph.json"
sbt#
이 방법은 sbt-dependency-graph
플러그인을 사용해 직접 의존성과 전이 의존성을 포함하여 분석기에 필요한 모든 정보가 담긴
dependencies-compile.dot 파일을 생성합니다.
sbt 프로젝트에서 분석기를 활성화하려면 다음과 같이 합니다.
Dependency-Scanning.v2CI/CD 템플릿을 추가합니다.plugins.sbt를 편집하여sbt-dependency-graph플러그인을 추가합니다.- 프로젝트의 기존 빌드 job에
sbt dependencyDot명령을 추가하거나, 빌드 job이 없으면 전용 job을 만듭니다. 스캔이 시작될 때 아티팩트를 사용할 수 있도록 이 job은dependency-scanningjob보다 먼저 실행되어야 합니다. dependencies-compile.dot을 job 아티팩트로 선언합니다.
기존 빌드 job에 명령을 추가하면 빌드의 sbt 세션과 해석된 구성을 재사용하므로 별도의 job에서 실행하는 것보다 빠릅니다.
예를 들면 다음과 같습니다.
stages:
- build
- test
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
build:
# Running in the build stage ensures that the dependency-scanning job
# receives the dependencies-compile.dot artifact.
stage: build
image: "sbtscala/scala-sbt:eclipse-temurin-17.0.13_11_1.10.7_3.6.3"
script:
# Your regular build script
- sbt compile
# New instruction to generate the dependency graph
- sbt dependencyDot
# Make the artifact available to the dependency-scanning job.
artifacts:
paths:
- "**/dependencies-compile.dot"
매니페스트 폴백#
히스토리
지원되는 잠금 파일이나 의존성 그래프 내보내기를 사용할 수 없을 때, 의존성 스캔 분석기는 지원되는 매니페스트 파일에서 폴백으로 의존성을 추출할 수 있습니다.
다음 매니페스트 파일이 지원됩니다.
| 언어 | 패키지 매니저 | 매니페스트 파일 |
|---|---|---|
| Java | Maven | pom.xml |
| Python | pip | requirements.txt |
| Java | Gradle | build.gradle, build.gradle.kts |
매니페스트 폴백은 잠금 파일 스캔에 비해 정확도가 낮습니다.
- 전이 의존성 없음: 직접 의존성만 탐지됩니다.
- 해석된 정확한 버전을 항상 확인할 수는 없습니다.
매니페스트 폴백 비활성화#
매니페스트 폴백을 비활성화하려면 DS_ENABLE_MANIFEST_FALLBACK CI/CD 변수 또는 enable_manifest_fallback 입력을 사용합니다.
variables:
DS_ENABLE_MANIFEST_FALLBACK: "false"
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
DS_ENABLE_MANIFEST_FALLBACK가 "false"이고 디렉터리에 매니페스트 파일은 있지만
잠금 파일이나 의존성 그래프 내보내기가 없으면 분석기는 다음과 같이 동작합니다.
- 성공적으로 해석된 모든 디렉터리의 SBOM과 결과를 기록합니다.
- 매니페스트에서 파생된 결과를 SBOM에서 제외하고 미포함으로 표시합니다.
- 0이 아닌 상태로 종료하며 영향을 받은 각 매니페스트 파일의 이름을 표시합니다.
즉, 이전에는 문제가 없는 것처럼 보였던 스캔(종료 코드 0, 결과 없음)이, 매니페스트 폴백 없이는 해석할 수 없는 프로젝트가 있으면 이제 눈에 띄게 실패합니다.
Maven(pom.xml), Gradle(build.gradle, build.gradle.kts), pip
(requirements.txt)만 매니페스트 파서가 있습니다. package.json
또는 Gemfile만 있는 디렉터리는 이 검사의 대상이 아닙니다. 또한 Gradle 서브프로젝트는
그 위의 가장 가까운 빌드 루트에 gradle-html-dependency-report.js 파일이 있을 때만 예외로 처리됩니다.
애플리케이션 스캔 방식#
SBOM을 사용한 의존성 스캔 기능은 의존성 탐지를 정적 도달 가능성이나 취약점 스캔 같은 다른 분석과 분리하는 분해된 의존성 분석 방식에 기반합니다.
이러한 관심사의 분리와 아키텍처의 모듈성 덕분에 언어 지원 확장, GitLab 플랫폼 내에서의 더 긴밀한 통합과 경험, 업계 표준 보고서 유형으로의 전환을 통해 고객을 더 잘 지원할 수 있습니다.
의존성 해석이 활성화되면 해석 job은 dependency-scanning job보다
먼저 .pre 스테이지에서 실행됩니다. 이 job은 잠금 파일이나
의존성 그래프 내보내기를 아티팩트로 생성하고, dependency-scanning job이 이를 사용합니다.
의존성 스캔의 전체 흐름은 아래와 같습니다.
소스 코드 보기
flowchart TD
subgraph CI[CI Pipeline]
START([CI Job Starts])
DETECT[Dependency Detection]
SBOM_GEN[SBOM Reports Generation]
SR[Static Reachability Analysis]
UPLOAD[Upload SBOM Files]
DL[Download Scan Results]
REPORT[DS Security Report Generation]
END([CI Job Complete])
end
subgraph GitLab[GitLab Instance]
API[CI SBOM Scan API]
SCANNER[GitLab SBOM Vulnerability Scanner]
RESULTS[Scan Results]
end
START --> DETECT
DETECT --> SBOM_GEN
SBOM_GEN --> SR
SR --> UPLOAD
UPLOAD --> API
API --> SCANNER
SCANNER --> RESULTS
RESULTS --> DL
DL --> REPORT
REPORT --> END</code></pre></details></div>
의존성 탐지 단계에서 분석기는 사용 가능한 잠금 파일을 파싱하여 프로젝트 의존성과 그 관계(의존성 그래프)의 포괄적인 목록을 구축합니다. 이 목록은 CycloneDX SBOM(소프트웨어 자재 명세서) 문서에 기록됩니다.
정적 도달 가능성 단계에서 분석기는 소스 파일을 파싱하여 어떤 SBOM 컴포넌트가 실제로 사용되는지 식별하고 SBOM 파일에 그에 맞게 표시합니다.
이를 통해 사용자는 취약한 컴포넌트에 도달할 수 있는지 여부를 기준으로 취약점의 우선순위를 정할 수 있습니다.
자세한 내용은 정적 도달 가능성 페이지를 참고합니다.
SBOM 문서는 의존성 스캔 SBOM API를 통해 GitLab 인스턴스에 임시로 업로드됩니다.
GitLab SBOM 취약점 스캐너 엔진은 SBOM 컴포넌트를 어드바이저리와 대조하여 결과 목록을 생성하며, 이 목록은 분석기에 반환되어 의존성 스캔 보고서에 포함됩니다.
이 API는 인증에 기본 CI_JOB_TOKEN을 사용합니다. CI_JOB_TOKEN 값을 다른 토큰으로 재정의하면 API에서 403 Forbidden 응답이 반환될 수 있습니다.
사용자는 다음을 사용하여 의존성 스캔 SBOM API와 통신하는 분석기 클라이언트를 구성할 수 있습니다.
vulnerability_scan_api_timeout 또는 DS_API_TIMEOUT
vulnerability_scan_api_download_delay 또는 DS_API_SCAN_DOWNLOAD_DELAY
자세한 내용은 사용 가능한 spec 입력과 사용 가능한 CI/CD 변수를 참고합니다.
생성된 보고서는 CI job이 완료될 때 GitLab 인스턴스에 업로드되며 대개 파이프라인 완료 후에 처리됩니다.
SBOM 보고서는 의존성 목록, 라이선스 스캔, 지속적 취약점 스캔과 같은 다른 SBOM 기반 기능을 지원하는 데 사용됩니다.
의존성 스캔 보고서는 보안 스캔 결과의 일반적인 처리 과정을 따릅니다.
- 의존성 스캔 보고서를 기본 브랜치의 CI/CD job이 선언하면 취약점이 생성되며,
취약점 보고서에서 확인할 수 있습니다.
- 의존성 스캔 보고서를 기본이 아닌 브랜치의 CI/CD job이 선언하면 보안 결과가 생성되며,
파이프라인 보기의 보안 탭과 머지 리퀘스트 보고서에서 확인할 수 있습니다.
오프라인 환경#
인터넷을 통한 외부 리소스 접근이 제한되거나 차단되었거나 간헐적인 환경의 인스턴스에서는
의존성 스캔 job을 성공적으로 실행하려면 몇 가지 조정이 필요합니다.
자세한 내용은 오프라인 환경을 참고합니다.
요구 사항#
오프라인 환경에서 의존성 스캔을 실행하려면 다음이 필요합니다.
docker 또는 kubernetes 실행기를 사용하는 GitLab Runner.
- 의존성 스캔 분석기 이미지의 로컬 복사본.
- 패키지 메타데이터 데이터베이스에 대한 접근. 의존성의 라이선스 및 어드바이저리 데이터를 가져오는 데 필요합니다.
분석기 이미지의 로컬 복사본#
의존성 스캔 분석기를 사용하려면 다음과 같이 합니다.
-
현재 이미지를 registry.gitlab.com에서
로컬 Docker 컨테이너 레지스트리로 가져옵니다.
Docker 이미지를 로컬 오프라인 Docker 레지스트리로 가져오는 절차는
네트워크 보안 정책에 따라 다릅니다. IT 담당자와 상의하여 외부 리소스를 가져오거나
임시로 접근할 수 있는 승인된 절차를 확인합니다.
이 이미지는 새 기능, 버그 수정, 패치와 함께 정기적으로 업데이트되므로
정기적으로 다운로드하는 것이 좋을 수 있습니다. 오프라인 인스턴스가
GitLab 레지스트리에 접근할 수 있다면 Security-Binaries 템플릿을 사용해 최신 의존성 스캔 분석기 이미지를 다운로드할 수 있습니다.
-
로컬 분석기를 사용하도록 GitLab CI/CD를 구성합니다.
CI/CD 변수 SECURE_ANALYZERS_PREFIX 또는 analyzer_image_prefix spec 입력의 값을 로컬 Docker 레지스트리로 설정합니다. 이
예시에서는 docker-registry.example.com입니다.
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
variables:
SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
여러 프로젝트에서 스캔 적용#
보안 정책을 사용해 여러 프로젝트에 의존성 스캔을 적용합니다. 의존성 스캔에는
잠금 파일 또는 의존성 그래프 내보내기 같은 스캔 가능한 아티팩트가 필요합니다. 스캔 가능한
아티팩트가 프로젝트의 리포지터리에 커밋되어 있는지 여부에 따라 사용할 정책이 결정됩니다.
-
스캔 가능한 아티팩트가 리포지터리에 커밋되어 있다면
스캔 실행 정책을 사용합니다.
스캔 가능한 아티팩트가 리포지터리에 커밋되어 있거나 의존성 해석이
지원하는 프로젝트에서는 스캔 실행
정책이 의존성 스캔을 적용하는 가장 직접적인 방법입니다.
-
스캔 가능한 아티팩트가 리포지터리에 커밋되어 있지 않고 의존성 해석도
지원하지 않는다면
파이프라인 실행 정책을 사용합니다.
스캔 가능한 아티팩트가 리포지터리에 커밋되어 있지 않은 프로젝트에서는
파이프라인 실행 정책을 사용해야 합니다. 정책은 의존성 스캔을 호출하기 전에 스캔 가능한
아티팩트를 생성하는 사용자 정의 CI/CD job을 정의해야 합니다.
파이프라인 실행 정책은 다음을 충족해야 합니다.
- CI/CD 파이프라인의 일부로 잠금 파일이나 의존성 그래프 내보내기를 생성합니다.
- 프로젝트별 요구 사항에 맞게 의존성 탐지 과정을 사용자 정의합니다.
- Gradle, Maven 같은 빌드 도구에 대한 언어별 지침을 구현합니다.
다음 예시는 Gradle nebula 플러그인을 사용해 잠금 파일을 생성합니다. 다른 언어는
잠금 파일 또는 의존성 그래프 내보내기 수동 생성을 참고합니다.
예시: Gradle 프로젝트를 위한 파이프라인 실행 정책#
리포지터리에 스캔 가능한 아티팩트가 커밋되어 있지 않은 Gradle 프로젝트에서는 파이프라인 실행 정책에
아티팩트 생성 단계를 정의해야 합니다. 다음 예시는 nebula
플러그인을 사용합니다.
-
전용 보안 정책 프로젝트에서 기본 정책 파일(예: policy.yml)을
생성하거나 업데이트합니다.
pipeline_execution_policy:
- name: Enforce Gradle dependency scanning with SBOM
description: Generate dependency artifact and run dependency scanning.
enabled: true
pipeline_config_strategy: inject_policy
content:
include:
- project: $SECURITY_POLICIES_PROJECT
file: "dependency-scanning.yml"
-
dependency-scanning.yml 정책 파일을 추가합니다.
stages:
- build
- test
include:
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
generate nebula lockfile:
image: openjdk:11-jdk
stage: build
script:
- |
cat << EOF > nebula.gradle
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:12.7.1'
}
}
allprojects {
apply plugin: nebula.plugin.dependencylock.DependencyLockPlugin
}
EOF
./gradlew --init-script nebula.gradle -PdependencyLock.includeTransitives=true -PdependencyLock.lockFile=dependencies.lock generateLock saveLock
./gradlew --init-script nebula.gradle -PdependencyLock.includeTransitives=false -PdependencyLock.lockFile=dependencies.direct.lock generateLock saveLock
after_script:
- find . -path '*/build/dependencies.lock' -print -delete
artifacts:
paths:
- '**/dependencies.lock'
- '**/dependencies.direct.lock'
이 방식은 다음을 보장합니다.
- Gradle 프로젝트에서 파이프라인을 실행하면 스캔 가능한 아티팩트가 생성됩니다.
- 의존성 스캔이 적용되며 스캔 가능한 아티팩트에 접근할 수 있습니다.
- 정책 범위의 모든 프로젝트가 동일한 의존성 스캔 방식을 일관되게 따릅니다.
- 구성 변경을 중앙에서 관리하고 여러 프로젝트에 적용할 수 있습니다.
새 의존성 스캔 기능을 활성화하는 다른 방법#
v2 템플릿을 사용해 의존성 스캔 기능을 활성화하기를 강력히 권장합니다.
이것이 불가능한 경우 다음 방법 중 하나를 선택할 수 있습니다.
latest 템플릿 사용#
Warning
latest 템플릿은 안정적인 것으로 간주되지 않으며 호환성을 깨는 변경이 포함될 수 있습니다. 템플릿 에디션을 참고합니다.
latest 의존성 스캔 CI/CD 템플릿 Dependency-Scanning.latest.gitlab-ci.yml을 사용하여 GitLab이 제공하는 분석기를 활성화합니다.
-
(사용 중단된) Gemnasium 분석기가 기본으로 사용됩니다.
-
새 의존성 스캔 분석기를 활성화하려면 CI/CD 변수 DS_ENFORCE_NEW_ANALYZER를 true로 설정합니다.
-
파이프라인에 dependency-scanning job을 생성하려면 리포지터리에 지원되는 잠금 파일 또는 의존성 그래프 내보내기 또는 트리거 파일이 있어야 합니다.
include:
- template: Jobs/Dependency-Scanning.latest.gitlab-ci.yml
variables:
DS_ENFORCE_NEW_ANALYZER: 'true'
latest 템플릿과 함께 스캔 실행 정책을 사용하고 CI/CD 변수 DS_ENFORCE_NEW_ANALYZER를 true로 설정해 새 의존성 스캔 분석기를 적용하는 방법으로도 이 기능을 활성화할 수 있습니다.
분석기 동작을 사용자 정의하려면 사용 가능한 CI/CD 변수를 사용합니다.
latest 템플릿의 트리거 파일#
트리거 파일은 latest 의존성 스캔 CI/CD 템플릿을 사용할 때 dependency-scanning CI/CD job을 생성합니다.
분석기는 이 파일을 스캔하지 않습니다.
트리거 파일을 사용해 잠금 파일 또는 의존성 그래프 내보내기를 수동으로 생성하면 프로젝트가 지원될 수 있습니다.
언어
파일
C#/Visual Basic
*.csproj, *.vbproj
Java
pom.xml
Java/Kotlin
build.gradle, build.gradle.kts
Python
requirements.pip, Pipfile, requires.txt, setup.py
Scala
build.sbt
의존성 스캔 CI/CD 컴포넌트 사용#
히스토리
- GitLab 17.5에서 베타로 도입되었습니다. 의존성 스캔 CI/CD 컴포넌트 버전
0.4.0.
- GitLab 18.8에서 정식 출시되었습니다. 의존성 스캔 CI/CD 컴포넌트 버전
1.0.0.
새 의존성 스캔 분석기를 활성화하려면
의존성 스캔 CI/CD 컴포넌트를
사용합니다. 이 방법을 선택하기 전에 GitLab Self-Managed의 현재
제한 사항을 검토합니다.
include:
- component: $CI_SERVER_FQDN/components/dependency-scanning/main@1
잠금 파일 또는 의존성 그래프 내보내기를 수동으로 생성도 해야 합니다.
의존성 스캔 CI/CD 컴포넌트를 사용하면 입력을 구성하여 분석기를 사용자 정의할 수 있습니다.
자체 SBOM 사용#
Warning
서드파티 SBOM 지원은 기술적으로 가능하지만, 이 에픽으로 공식 지원을 완료하는 과정에서 크게 바뀔 수 있습니다.
서드파티 CycloneDX SBOM 생성기나 사용자 정의 도구로 생성한 자체 CycloneDX SBOM 문서를 사용자 정의 CI job에서 CI/CD 아티팩트 보고서로 사용합니다.
SBOM을 사용한 의존성 스캔을 활성화하려면 제공하는 CycloneDX SBOM 문서가 다음을 충족해야 합니다.
- CycloneDX 명세 버전
1.4, 1.5 또는 1.6을 준수합니다. 온라인 검증기는 CycloneDX Web Tool에서 사용할 수 있습니다.
- GitLab CycloneDX 속성 분류 체계를 준수합니다.
- 성공한 CI job에서 CI/CD 아티팩트 보고서로 업로드되어야 합니다.
Footnotes
-
cocoapods PURL 유형은 지원되는 패키지 유형이 아닙니다.
iOS 프로젝트에서 의존성 목록과 취약점 스캔 범위를 모두 확보하려면
대신 Package.resolved와 함께 Swift Package Manager를 사용합니다. ↩
-
잠금 파일에 환경 마커가 서로 다른 동일 패키지 항목이 여러 개 있는 경우(예: Python <3.11의 numpy==2.2.6과 Python ≥3.11의 numpy==2.4.1) 첫 번째 항목만 파싱되어 보고됩니다. ↩