InfoGrab DocsInfoGrab Docs

의존성 스캐닝

요약

Gemnasium 분석기 기반 의존성 스캔 기능은 GitLab 17.9에서 더 이상 사용되지 않으며(deprecated), GitLab 20.0에서 제거될 예정입니다. 의존성 스캔은 CI/CD 파이프라인에 통합되어 자동으로 실행되며, 애플리케이션 의존성의 보안 취약점을 식별합니다.

Warning

Gemnasium 분석기 기반 의존성 스캔 기능은 GitLab 17.9에서 더 이상 사용되지 않으며(deprecated), GitLab 20.0에서 제거될 예정입니다. 다만 제거 시점은 확정되지 않았으며, 필요에 따라 Gemnasium을 계속 사용할 수 있습니다. 자세한 내용은 에픽 15961을 참고합니다.

의존성 스캔은 CI/CD 파이프라인에 통합되어 자동으로 실행되며, 애플리케이션 의존성의 보안 취약점을 식별합니다. 브랜치를 병합하기 전에 스캔하면 머지 리퀘스트에서 보안 문제를 즉시 확인할 수 있습니다. 이를 통해 코드를 병합하기 전에 잠재적 취약점에 대해 충분한 정보를 바탕으로 결정을 내릴 수 있습니다.

기본적으로 의존성 스캔은 런타임, 개발, 전이(중첩) 의존성을 포함해 코드의 모든 의존성을 분석합니다. 필요에 따라 스캔에서 개발 의존성을 제외할 수 있습니다.

파이프라인 밖에서 의존성의 취약점을 스캔하려면 지속적 취약점 스캔을 참고합니다.

의존성 스캔 켜기#

다음 단계에 따라 프로젝트에서 의존성 스캔을 켭니다.

분석기를 사용 설정하려면 다음 중 하나를 수행합니다.

사전 구성된 머지 리퀘스트 사용#

이 방법은 .gitlab-ci.yml 파일에 의존성 스캔 템플릿을 포함한 머지 리퀘스트를 자동으로 준비합니다. 그런 다음 머지 리퀘스트를 병합하면 의존성 스캔이 사용 설정됩니다.

Note

이 방법은 기존 .gitlab-ci.yml 파일이 없거나 최소한의 구성 파일만 있을 때 가장 잘 동작합니다. GitLab 구성 파일이 복잡하면 파싱에 성공하지 못해 오류가 발생할 수 있습니다. 그 경우에는 수동 방법을 대신 사용합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.
  • .gitlab-ci.yml 파일에 test Stage가 있어야 합니다.
  • 자체 관리형 러너의 경우 docker 또는 kubernetes executor를 사용하는 GitLab Runner.
  • GitLab.com의 호스팅 러너는 이 구성이 기본적으로 사용 설정되어 있습니다.

의존성 스캔을 켜려면 다음을 수행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Secure > Security configuration을 선택합니다.
  3. Dependency Scanning 행에서 Configure with a merge request를 선택합니다.
  4. Create merge request를 선택합니다.
  5. 머지 리퀘스트를 검토한 다음 Merge를 선택합니다.

이제 파이프라인에 의존성 스캔 job이 포함됩니다.

.gitlab-ci.yml 파일 직접 편집#

이 방법은 기존 .gitlab-ci.yml 파일을 직접 편집해야 합니다. GitLab CI/CD 구성 파일이 복잡한 경우 이 방법을 사용합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.
  • .gitlab-ci.yml 파일에 test Stage가 있어야 합니다.
  • 자체 관리형 러너의 경우 docker 또는 kubernetes executor를 사용하는 GitLab Runner.
  • GitLab.com의 호스팅 러너는 이 구성이 기본적으로 사용 설정되어 있습니다.

의존성 스캔을 켜려면 다음을 수행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.

  2. 왼쪽 사이드바에서 Build > Pipeline editor를 선택합니다.

  3. .gitlab-ci.yml 파일이 없으면 Configure pipeline을 선택한 다음 예시 내용을 삭제합니다.

  4. 다음을 복사해 .gitlab-ci.yml 파일 맨 아래에 붙여넣습니다. include 줄이 이미 있으면 그 아래에 template 줄만 추가합니다.

    include:
      - template: Jobs/Dependency-Scanning.gitlab-ci.yml
    
  5. Validate 탭을 선택한 다음 Validate pipeline을 선택합니다.

    Simulation completed successfully 메시지가 표시되면 파일이 유효한 것입니다.

  6. Edit 탭을 선택합니다.

  7. 필드를 입력합니다. Branch 필드에는 기본 브랜치를 사용하지 않습니다.

  8. Start a new merge request with these changes 체크박스를 선택한 다음 Commit changes를 선택합니다.

  9. 표준 워크플로에 따라 필드를 입력한 다음 Create merge request를 선택합니다.

  10. 표준 워크플로에 따라 머지 리퀘스트를 검토하고 편집한 다음 Merge를 선택합니다.

이제 파이프라인에 의존성 스캔 job이 포함됩니다.

CI/CD 컴포넌트 사용#

Note

의존성 스캔 CI/CD 컴포넌트는 Android 프로젝트만 지원합니다.

CI/CD 컴포넌트를 사용해 애플리케이션의 의존성 스캔을 수행합니다. 방법은 해당 컴포넌트의 README 파일을 참고합니다.

사용 가능한 CI/CD 컴포넌트#

https://gitlab.com/explore/catalog/components/dependency-scanning을 참고합니다.

이 단계를 완료하면 다음을 할 수 있습니다.

결과 이해#

의존성 스캔 결과는 여러 형식으로 제공됩니다. 파이프라인 UI, 상세 스캔 보고서, 또는 스캔 중 생성되는 소프트웨어 자재 명세서(SBOM, Software Bill of Materials)에서 직접 확인할 수 있습니다.

파이프라인의 취약점 검토#

파이프라인에서 탐지된 취약점을 검토하고 머지 리퀘스트가 병합되기 전에 조치합니다.

사전 요구 사항:

  • 프로젝트의 Developer, Maintainer 또는 Owner 권한.

파이프라인에서 의존성 스캔 결과를 검토하려면 다음을 수행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Build > Pipelines를 선택합니다.
  3. 파이프라인을 선택합니다.
  4. Security 탭을 선택합니다.
  5. 취약점을 선택하면 다음을 포함한 세부 정보를 볼 수 있습니다.
    • Status: 취약점이 분류(triage)되었는지 또는 해결되었는지를 나타냅니다.
    • Description: 취약점의 원인, 잠재적 영향, 권장 해결 단계를 설명합니다.
    • Severity: 영향도에 따라 6단계로 분류됩니다. 심각도 수준에 대해 자세히 알아봅니다.
    • CVSS score: 심각도에 대응하는 수치 값을 제공합니다.
    • EPSS: 취약점이 실제로 악용될 가능성을 보여 줍니다.
    • Has Known Exploit (KEV): 해당 취약점이 악용된 적이 있음을 나타냅니다.
    • Project: 취약점이 식별된 프로젝트를 강조해 표시합니다.
    • Report type / Scanner: 출력 유형과 해당 출력을 생성한 스캐너를 설명합니다.
    • Reachable: 취약한 의존성이 코드에서 사용되는지 여부를 나타냅니다.
    • Scanner: 어떤 분석기가 취약점을 탐지했는지 식별합니다.
    • Location: 취약한 의존성이 있는 파일을 나타냅니다.
    • Links: 취약점이 여러 어드바이저리 데이터베이스에 등재되었다는 근거입니다.
    • Identifiers: CVE 식별자 등 취약점을 분류하는 데 사용되는 참조 목록입니다.

의존성 스캔 보고서#

의존성 스캔은 모든 취약점의 세부 정보를 담은 보고서를 출력합니다. 이 보고서는 내부적으로 처리되어 결과가 UI에 표시됩니다. 보고서는 의존성 스캔 job의 아티팩트로도 출력되며 이름은 gl-dependency-scanning-report.json이고, 항상 프로젝트의 루트에 생성됩니다.

의존성 스캔 보고서에 대한 자세한 내용은 의존성 스캔 보고서 스키마를 참고합니다.

CycloneDX 소프트웨어 자재 명세서#

의존성 스캔은 감지한 지원 대상 잠금 파일 또는 빌드 파일마다 CycloneDX 소프트웨어 자재 명세서(SBOM)를 출력합니다.

CycloneDX SBOM은 다음과 같습니다.

  • 이름은 gl-sbom-<package-type>-<package-manager>.cdx.json입니다.
  • 의존성 스캔 job의 job 아티팩트로 제공됩니다.
  • 감지된 잠금 파일 또는 빌드 파일과 같은 디렉터리에 저장됩니다.

예를 들어 프로젝트가 다음과 같은 구조라고 가정합니다.

.
├── ruby-project/
│   └── Gemfile.lock
├── ruby-project-2/
│   └── Gemfile.lock
├── php-project/
│   └── composer.lock
└── go-project/
    └── go.sum

이 경우 Gemnasium 스캐너는 다음 CycloneDX SBOM을 생성합니다.

.
├── 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
└── go-project/
    ├── go.sum
    └── gl-sbom-go-go.cdx.json

단계적 적용#

단일 프로젝트의 의존성 스캔 결과를 신뢰할 수 있게 되면 다른 프로젝트로 적용 범위를 넓힐 수 있습니다.

  • 강제 스캔 실행을 사용해 여러 그룹에 의존성 스캔 설정을 적용합니다.
  • 고유한 요구 사항이 있으면 SBOM을 사용하는 의존성 스캔을 오프라인 환경에서 실행할 수 있습니다.

지원되는 언어 및 패키지 관리자#

Note

의존성 스캔은 컴파일러와 인터프리터의 런타임 설치를 지원하지 않습니다.

의존성 스캔은 다음 언어와 의존성 관리자를 지원합니다.

언어 언어 버전 패키지 관리자 지원되는 파일 여러 파일 처리 여부
.NET 모든 버전 NuGet packages.lock.json Y
C#
C 모든 버전 Conan conan.lock Y
C++
Go 모든 버전 Go
  • go.sum
Y
Java 및 Kotlin 8 LTS, 11 LTS, 17 LTS, 또는 21 LTS1 Gradle2
  • build.gradle
  • build.gradle.kts
N
Maven6 pom.xml N
JavaScript 및 TypeScript 모든 버전 npm
  • package-lock.json
  • npm-shrinkwrap.json
Y
yarn yarn.lock Y
pnpm3 pnpm-lock.yaml Y
PHP 모든 버전 Composer composer.lock Y
Python 3.117 setuptools8 setup.py N
pip
  • requirements.txt
  • requirements.pip
  • requires.txt
N
Pipenv N
Poetry4 poetry.lock N
uv11 uv.lock Y
Ruby 모든 버전 Bundler
  • Gemfile.lock
  • gems.locked
Y
Scala 모든 버전 sbt5 build.sbt N
Swift 모든 버전 Swift Package Manager Package.resolved N
CocoaPods9 모든 버전 CocoaPods Podfile.lock N
Dart10 모든 버전 Pub pubspec.lock N

각주:

  1. sbt의 Java 21 LTS는 1.9.7 버전으로 제한됩니다. 더 많은 sbt 버전에 대한 지원은 이슈 430335에서 추적할 수 있습니다. FIPS 모드가 사용 설정되어 있으면 지원되지 않습니다.
  2. FIPS 모드가 사용 설정되어 있으면 Gradle은 지원되지 않습니다.
  3. pnpm 잠금 파일은 번들된 의존성을 저장하지 않으므로 보고되는 의존성이 npm 또는 yarn과 다를 수 있습니다.
  4. poetry.lock 파일이 없는 프로젝트에 대한 지원은 이슈 32774에서 추적합니다.
  5. sbt 1.0.x 지원은 GitLab 16.8에서 더 이상 사용되지 않게 되었고 GitLab 17.0에서 제거되었습니다.
  6. 3.8.8 미만 Maven 지원은 GitLab 16.9에서 더 이상 사용되지 않게 되었고 GitLab 17.0에서 제거되었습니다.
  7. 이전 Python 버전 지원은 GitLab 16.9에서 더 이상 사용되지 않게 되었고 GitLab 17.0에서 제거되었습니다.
  8. 설치 프로그램에 필요하므로 pip와 setuptools는 모두 보고서에서 제외됩니다.
  9. 권고 정보 없이 SBOM만 제공됩니다. 이슈 468764를 참고합니다.
  10. 라이선스 탐지는 지원되지 않습니다. 에픽 17037을 참고합니다.
  11. 잠금 파일에 같은 패키지에 대해 환경 마커가 다른 항목이 여러 개 있으면(예: Python <3.11용 numpy==2.2.6과 Python ≥3.11용 numpy==2.4.1) 첫 번째 항목만 파싱되어 보고됩니다.

지원되는 개발 의존성#

개발 의존성 탐지는 다음 언어와 패키지 관리자에서 지원됩니다.

언어 패키지 관리자 파일
C/C++/Fortran/Go/Python/R conda conda-lock.yml
Java Maven maven.graph.json
Java/Kotlin Gradle dependencies.lock, dependencies.direct.lock, gradle-html-dependency-report.js, gradle.lockfile
JavaScript/TypeScript npm package-lock.json, npm-shrinkwrap.json
JavaScript/TypeScript pnpm pnpm-lock.yaml
PHP Composer composer.lock
Python Pipenv Pipfile.lock
Python Poetry poetry.lock
Python uv uv.lock

머지 리퀘스트 파이프라인에서 job 실행#

머지 리퀘스트 파이프라인에서 보안 스캔 도구 사용을 참고합니다.

분석기 동작 사용자 지정#

의존성 스캔을 사용자 지정하려면 CI/CD 변수를 사용합니다.

Warning

GitLab 분석기의 모든 사용자 지정은 기본 브랜치에 병합하기 전에 머지 리퀘스트에서 테스트합니다. 그렇지 않으면 다수의 오탐을 포함해 예기치 않은 결과가 발생할 수 있습니다.

의존성 스캔 job 재정의#

job 정의를 재정의하려면(예: variables 또는 dependencies 같은 속성 변경), 재정의할 job과 같은 이름으로 새 job을 선언합니다. 이 새 job은 템플릿 포함(include) 뒤에 배치하고 그 아래에 필요한 추가 키를 지정합니다.

예를 들어 다음은 gemnasium 분석기의 취약한 의존성 자동 해결을 비활성화합니다.

include:
  - template: Jobs/Dependency-Scanning.gitlab-ci.yml

gemnasium-dependency_scanning:
  variables:
    DS_REMEDIATE: "false"

dependencies: [] 속성을 재정의하려면 앞에서 설명한 대로 이 속성을 대상으로 하는 재정의 job을 추가합니다.

include:
  - template: Jobs/Dependency-Scanning.gitlab-ci.yml

gemnasium-dependency_scanning:
  dependencies: ["build"]

사용 가능한 CI/CD 변수#

CI/CD 변수를 사용해 의존성 스캔 동작을 사용자 지정할 수 있습니다.

전역 분석기 설정#

다음 변수로 전역 의존성 스캔 설정을 구성할 수 있습니다.

CI/CD 변수 설명
ADDITIONAL_CA_CERT_BUNDLE 신뢰할 CA 인증서 번들입니다. 여기에 제공한 인증서 번들은 스캔 과정에서 git, yarn, npm 같은 다른 도구에서도 사용됩니다. 자세한 내용은 사용자 지정 TLS 인증 기관을 참고합니다.
DS_EXCLUDED_ANALYZERS 의존성 스캔에서 제외할 분석기를 이름으로 지정합니다. 자세한 내용은 분석기를 참고합니다.
DS_EXCLUDED_PATHS 경로를 기준으로 스캔에서 파일과 디렉터리를 제외합니다. 패턴을 쉼표로 구분한 목록입니다. 패턴은 glob(지원되는 패턴은 doublestar.Match 참고)이거나 파일 또는 폴더 경로(예: doc,spec)일 수 있습니다. 상위 디렉터리도 패턴과 일치합니다. 스캔이 실행되기 전에 적용되는 사전 필터입니다. 기본값: "spec, test, tests, tmp".
DS_IMAGE_SUFFIX 이미지 이름에 추가되는 접미사입니다. (GitLab 팀 구성원은 이 비공개 이슈에서 더 많은 정보를 볼 수 있습니다: https://gitlab.com/gitlab-org/gitlab/-/issues/354796). FIPS 모드가 사용 설정되면 자동으로 "-fips"로 설정됩니다.
DS_MAX_DEPTH 분석기가 스캔할 지원 대상 파일을 몇 단계 깊이의 디렉터리까지 검색할지 정의합니다. 값이 -1이면 깊이에 관계없이 모든 디렉터리를 스캔합니다. 기본값: 2.
SECURE_ANALYZERS_PREFIX 공식 기본 이미지를 제공하는 Docker 레지스트리(프록시)의 이름을 재정의합니다.

분석기별 설정#

다음 변수로 특정 의존성 스캔 분석기의 동작을 구성합니다.

CI/CD 변수 분석기 기본값 설명
GEMNASIUM_DB_LOCAL_PATH gemnasium /gemnasium-db 로컬 Gemnasium 데이터베이스의 경로입니다.
GEMNASIUM_DB_UPDATE_DISABLED gemnasium "false" gemnasium-db 어드바이저리 데이터베이스의 자동 업데이트를 비활성화합니다. 사용법은 GitLab 어드바이저리 데이터베이스 접근을 참고합니다.
GEMNASIUM_DB_REMOTE_URL gemnasium https://gitlab.com/gitlab-org/security-products/gemnasium-db.git GitLab 어드바이저리 데이터베이스를 가져올 리포지터리 URL입니다.
GEMNASIUM_DB_REF_NAME gemnasium master 원격 리포지터리 데이터베이스의 브랜치 이름입니다. GEMNASIUM_DB_REMOTE_URL이 필요합니다.
GEMNASIUM_IGNORED_SCOPES gemnasium 무시할 Maven 의존성 스코프를 쉼표로 구분한 목록입니다. 자세한 내용은 Maven 의존성 스코프 문서를 참고합니다.
DS_REMEDIATE gemnasium "true", FIPS 모드에서는 "false" 취약한 의존성의 자동 해결을 사용 설정합니다. FIPS 모드에서는 지원되지 않습니다.
DS_REMEDIATE_TIMEOUT gemnasium 5m 자동 해결의 제한 시간입니다.
GEMNASIUM_LIBRARY_SCAN_ENABLED gemnasium "true" 벤더링된 JavaScript 라이브러리(패키지 관리자가 관리하지 않는 라이브러리)의 취약점 탐지를 사용 설정합니다. 이 기능을 쓰려면 커밋에 JavaScript 잠금 파일이 있어야 하며, 없으면 의존성 스캔이 실행되지 않고 벤더링된 파일도 스캔되지 않습니다.
의존성 스캔은 Retire.js 스캐너를 사용해 제한된 범위의 취약점을 탐지합니다. 탐지되는 취약점에 대한 자세한 내용은 Retire.js 리포지터리를 참고합니다.
DS_INCLUDE_DEV_DEPENDENCIES gemnasium "true" "false"로 설정하면 개발 의존성과 그 취약점이 보고되지 않습니다. Composer, Maven, npm, pnpm, Pipenv 또는 Poetry를 사용하는 프로젝트만 지원됩니다.
GOOS gemnasium "linux" Go 코드를 컴파일할 대상 운영 체제입니다.
GOARCH gemnasium "amd64" Go 코드를 컴파일할 대상 프로세서의 아키텍처입니다.
GOFLAGS gemnasium go build 도구에 전달되는 플래그입니다.
GOPRIVATE gemnasium 소스에서 직접 가져올 glob 패턴과 접두사의 목록입니다. 자세한 내용은 Go 프라이빗 모듈 문서를 참고합니다.
DS_JAVA_VERSION gemnasium-maven 17 Java 버전입니다. 사용 가능한 버전: 8, 11, 17, 21.
MAVEN_CLI_OPTS gemnasium-maven "-DskipTests --batch-mode" 분석기가 maven에 전달하는 명령줄 인수의 목록입니다. 프라이빗 리포지터리 사용 예시를 참고합니다.
GRADLE_CLI_OPTS gemnasium-maven 분석기가 gradle에 전달하는 명령줄 인수의 목록입니다.
GRADLE_PLUGIN_INIT_PATH gemnasium-maven "gemnasium-init.gradle" Gradle 초기화 스크립트의 경로를 지정합니다. 호환성을 위해 초기화 스크립트에 allprojects { apply plugin: 'project-report' }가 포함되어야 합니다.
DS_GRADLE_RESOLUTION_POLICY gemnasium-maven "failed" Gradle 의존성 해석의 엄격도를 제어합니다. 부분 결과를 허용하려면 "none"을, 의존성 해석에 하나라도 실패하면 스캔을 실패 처리하려면 "failed"를 지정합니다.
SBT_CLI_OPTS gemnasium-maven 분석기가 sbt에 전달하는 명령줄 인수의 목록입니다.
PIP_INDEX_URL gemnasium-python https://pypi.org/simple Python Package Index의 기본 URL입니다.
PIP_EXTRA_INDEX_URL gemnasium-python PIP_INDEX_URL 외에 사용할 패키지 인덱스의 추가 URL 배열입니다. 쉼표로 구분합니다. Warning: 이 환경 변수를 사용할 때는 다음 보안 고려 사항을 읽어 봅니다.
PIP_REQUIREMENTS_FILE gemnasium-python 스캔할 Pip requirements 파일입니다. 경로가 아니라 파일 이름입니다. 이 환경 변수를 설정하면 지정한 파일만 스캔됩니다.
PIPENV_PYPI_MIRROR gemnasium-python 설정하면 Pipenv가 사용하는 PyPi 인덱스를 미러로 재정의합니다.
DS_PIP_VERSION gemnasium-python 특정 pip 버전(예: "19.3")의 설치를 강제합니다. 설정하지 않으면 Docker 이미지에 설치된 pip를 사용합니다.
DS_PIP_DEPENDENCY_PATH gemnasium-python Python pip 의존성을 불러올 경로입니다.

기타 변수#

앞의 표는 사용할 수 있는 모든 변수를 망라한 목록이 아닙니다. 이 표에는 지원되고 테스트된 GitLab 및 분석기 고유 변수가 모두 들어 있습니다. 환경 변수 같은 다른 많은 변수도 전달해서 올바르게 동작하게 할 수 있습니다. 이 목록은 방대하며 모두 문서화되어 있지는 않습니다.

예를 들어 GitLab 변수가 아닌 환경 변수 HTTPS_PROXY를 모든 의존성 스캔 job에 전달하려면 다음과 같이 .gitlab-ci.yml의 CI/CD 변수로 설정합니다.

variables:
  HTTPS_PROXY: "https://squid-proxy:3128"
Note

Gradle 프로젝트에서 프록시를 사용하려면 추가 변수를 설정해야 합니다.

또는 의존성 스캔 같은 특정 job에서만 사용할 수도 있습니다.

dependency_scanning:
  variables:
    HTTPS_PROXY: $HTTPS_PROXY

모든 변수를 테스트한 것은 아니므로 일부는 동작하고 일부는 동작하지 않을 수 있습니다. 동작하지 않는 변수가 필요하면 기능 요청을 제출하거나 해당 변수를 사용할 수 있도록 코드에 기여할 수 있습니다.

사용자 지정 TLS 인증 기관#

의존성 스캔에서는 분석기 컨테이너 이미지에 기본으로 포함된 인증서 대신 SSL/TLS 연결에 사용자 지정 TLS 인증서를 사용할 수 있습니다.

사용자 지정 인증 기관 지원은 다음 버전에서 도입되었습니다.

분석기 버전
gemnasium v2.8.0
gemnasium-maven v2.9.0
gemnasium-python v2.7.0

사용자 지정 TLS 인증 기관 사용#

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

사용자 지정 TLS 인증 기관을 사용하려면 다음을 수행합니다.

예를 들어 .gitlab-ci.yml 파일에서 인증서를 구성하려면 다음과 같이 합니다.

variables:
  ADDITIONAL_CA_CERT_BUNDLE: |
      -----BEGIN CERTIFICATE-----
      MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
      ...
      jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
      -----END CERTIFICATE-----

프라이빗 Maven 리포지터리로 인증#

의존성 분석기가 프라이빗 Maven 리포지터리로 인증할 수 있게 하려면 CI/CD 파이프라인에서 자격 증명을 구성해야 합니다. 인증하지 않으면 의존성 분석기가 프라이빗 의존성에 접근할 수 없어 스캔이 실패합니다.

Warning

자격 증명을 .gitlab-ci.yml 파일에 추가하지 않습니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

의존성 분석기가 프라이빗 Maven 리포지터리로 인증할 수 있게 하려면 다음을 수행합니다.

  1. MAVEN_CLI_OPTS라는 이름의 프로젝트 CI/CD 변수를 생성하고 값에 자격 증명이 포함되도록 설정합니다.

    예를 들어 설정 파일 이름이 mysettings.xml, 사용자 이름이 myuser, 비밀번호가 verysecret이라면 MAVEN_CLI_OPTS CI/CD 변수를 다음과 같이 설정합니다.

    --settings mysettings.xml -Drepository.password=verysecret -Drepository.user=myuser

  2. 서버 구성이 담긴 mysettings.xml Maven 설정 파일을 생성합니다. 파일 이름은 1단계에서 --settings 옵션에 지정한 값과 일치해야 합니다.

    <!-- mysettings.xml -->
    <settings>
        ...
        <servers>
            <server>
                <id>private_server</id>
                <username>${repository.user}</username>
                <password>${repository.password}</password>
            </server>
        </servers>
    </settings>
    

FIPS 지원 이미지#

GitLab은 Gemnasium 이미지의 FIPS 지원 Red Hat UBI 버전도 제공합니다. GitLab 인스턴스에서 FIPS 모드가 사용 설정되면 Gemnasium 스캔 job은 FIPS 지원 이미지를 자동으로 사용합니다. FIPS 지원 이미지로 직접 전환하려면 변수 DS_IMAGE_SUFFIX를 "-fips"로 설정합니다.

FIPS 모드에서는 Gradle 프로젝트의 의존성 스캔과 Yarn 프로젝트의 자동 해결이 지원되지 않습니다.

FIPS 지원 이미지는 RedHat의 UBI micro를 기반으로 합니다. 이 이미지에는 dnf나 microdnf 같은 패키지 관리자가 없으므로 런타임에 시스템 패키지를 설치할 수 없습니다.

오프라인 환경#

인터넷을 통한 외부 리소스 접근이 제한적이거나 차단되었거나 간헐적인 환경의 인스턴스에서는 의존성 스캔 job이 성공적으로 실행되도록 일부 조정이 필요합니다. 자세한 내용은 오프라인 환경을 참고합니다.

사전 요구 사항:

분석기 이미지의 로컬 사본#

모든 지원되는 언어 및 프레임워크에서 의존성 스캔을 사용하려면 다음을 수행합니다.

  1. registry.gitlab.com의 다음 기본 의존성 스캔 분석기 이미지를 로컬 Docker 컨테이너 레지스트리로 가져옵니다.

    registry.gitlab.com/security-products/gemnasium:6
    registry.gitlab.com/security-products/gemnasium:6-fips
    registry.gitlab.com/security-products/gemnasium-maven:6
    registry.gitlab.com/security-products/gemnasium-maven:6-fips
    registry.gitlab.com/security-products/gemnasium-python:6
    registry.gitlab.com/security-products/gemnasium-python:6-fips
    

    Docker 이미지를 로컬 오프라인 Docker 레지스트리로 가져오는 절차는 네트워크 보안 정책에 따라 다릅니다. 외부 리소스를 가져오거나 일시적으로 접근할 수 있는 허용되고 승인된 절차를 IT 담당자와 상의합니다. 이 스캐너는 새 정의로 주기적으로 업데이트되므로 정기적으로 내려받는 것이 좋을 수 있습니다.

  2. 로컬 분석기를 사용하도록 GitLab CI/CD를 구성합니다.

    CI/CD 변수 SECURE_ANALYZERS_PREFIX의 값을 로컬 Docker 레지스트리로 설정합니다. 이 예시에서는 docker-registry.example.com입니다.

    include:
      - template: Jobs/Dependency-Scanning.gitlab-ci.yml
    
    variables:
      SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
    

GitLab 어드바이저리 데이터베이스 접근#

GitLab 어드바이저리 데이터베이스는 gemnasium, gemnasium-maven, gemnasium-python 분석기가 사용하는 취약점 데이터의 원천입니다. 이 분석기의 Docker 이미지에는 데이터베이스의 클론이 포함되어 있습니다. 분석기가 최신 취약점 데이터를 사용하도록 스캔을 시작하기 전에 클론이 데이터베이스와 동기화됩니다.

오프라인 환경에서는 GitLab 어드바이저리 데이터베이스의 기본 호스트에 접근할 수 없습니다. 대신 GitLab 러너가 접근할 수 있는 곳에 데이터베이스를 호스팅해야 합니다. 또한 원하는 일정에 따라 데이터베이스를 직접 업데이트해야 합니다.

데이터베이스를 호스팅하는 방법은 다음과 같습니다.

GitLab 어드바이저리 데이터베이스의 클론 사용#

GitLab 어드바이저리 데이터베이스의 클론을 사용하는 방법이 가장 효율적이므로 권장됩니다.

GitLab 어드바이저리 데이터베이스의 클론을 호스팅하려면 다음을 수행합니다.

  1. GitLab 러너에서 HTTP로 접근할 수 있는 호스트에 GitLab 어드바이저리 데이터베이스를 클론합니다.
  2. .gitlab-ci.yml 파일에서 CI/CD 변수 GEMNASIUM_DB_REMOTE_URL의 값을 Git 리포지터리의 URL로 설정합니다.

예를 들면 다음과 같습니다.

variables:
  GEMNASIUM_DB_REMOTE_URL: https://users-own-copy.example.com/gemnasium-db.git
GitLab 어드바이저리 데이터베이스의 사본 사용#

GitLab 어드바이저리 데이터베이스의 사본을 사용하려면 분석기가 내려받는 아카이브 파일을 호스팅해야 합니다.

GitLab 어드바이저리 데이터베이스의 사본을 사용하려면 다음을 수행합니다.

  1. GitLab 러너에서 HTTP로 접근할 수 있는 호스트에 GitLab 어드바이저리 데이터베이스의 아카이브를 내려받습니다. 아카이브는 다음 위치에 있습니다. https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/archive/master/gemnasium-db-master.tar.gz.

  2. .gitlab-ci.yml 파일을 업데이트합니다.

    • 데이터베이스의 로컬 사본을 사용하도록 CI/CD 변수 GEMNASIUM_DB_LOCAL_PATH를 설정합니다.
    • 데이터베이스 업데이트를 비활성화하도록 CI/CD 변수 GEMNASIUM_DB_UPDATE_DISABLED를 설정합니다.
    • 스캔이 시작되기 전에 어드바이저리 데이터베이스를 내려받아 압축을 풉니다.
    variables:
      GEMNASIUM_DB_LOCAL_PATH: ./gemnasium-db-local
      GEMNASIUM_DB_UPDATE_DISABLED: "true"
    
    dependency_scanning:
      before_script:
        - wget https://local.example.com/gemnasium_db.tar.gz
        - mkdir -p $GEMNASIUM_DB_LOCAL_PATH
        - tar -xzvf gemnasium_db.tar.gz --strip-components=1 -C $GEMNASIUM_DB_LOCAL_PATH
    

Gradle 프로젝트에서 프록시 사용#

Gradle 래퍼 스크립트는 HTTP(S)_PROXY 환경 변수를 읽지 않습니다. 자세한 내용은 Gradle 이슈 11065를 참고합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

Gradle 래퍼 스크립트가 프록시를 사용하게 하려면 다음을 수행합니다.

  • GRADLE_CLI_OPTS CI/CD 변수로 프록시 옵션을 지정합니다.

    variables:
      GRADLE_CLI_OPTS: "-Dhttps.proxyHost=squid-proxy -Dhttps.proxyPort=3128 -Dhttp.proxyHost=squid-proxy -Dhttp.proxyPort=3128 -Dhttp.nonProxyHosts=localhost"
    

Maven 프로젝트에서 프록시 사용#

Maven은 HTTP(S)_PROXY 환경 변수를 읽지 않습니다. 대신 Maven 설정 파일을 사용해야 합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

Maven 의존성 스캐너가 프록시를 사용하도록 구성하려면 다음을 수행합니다.

  1. 프로젝트의 리포지터리에 mysettings.xml 파일을 생성합니다. 그 파일에서 Maven 프록시 설정을 구성합니다.

    프록시 구성을 지정하는 방법은 Maven 문서를 참고합니다.

  2. 프로젝트의 .gitlab-ci.yml 파일에서 MAVEN_CLI_OPTS CI/CD 변수를 정의해 설정 파일 mysettings.xml을 참조하게 합니다.

    variables:
      MAVEN_CLI_OPTS: "--settings mysettings.xml"
    

언어 및 패키지 관리자별 설정#

특정 언어와 패키지 관리자를 구성하는 방법은 다음 절을 참고합니다.

Python (pip)#

분석기를 실행하기 전에 Python 패키지를 설치해야 하면 스캔 job의 before_script에서 pip install --user를 사용해야 합니다. --user 플래그를 사용하면 프로젝트 의존성이 사용자 디렉터리에 설치됩니다. --user 옵션을 전달하지 않으면 패키지가 전역으로 설치되어 스캔되지 않으며 프로젝트 의존성을 나열할 때도 표시되지 않습니다.

Python (setuptools)#

분석기를 실행하기 전에 Python 패키지를 설치해야 하면 스캔 job의 before_script에서 python setup.py install --user를 사용해야 합니다. --user 플래그를 사용하면 프로젝트 의존성이 사용자 디렉터리에 설치됩니다. --user 옵션을 전달하지 않으면 패키지가 전역으로 설치되어 스캔되지 않으며 프로젝트 의존성을 나열할 때도 표시되지 않습니다.

프라이빗 PyPi 리포지터리에 자체 서명 인증서를 사용하는 경우 (앞의 .gitlab-ci.yml 템플릿 외에는) 추가 job 구성이 필요하지 않습니다. 다만 setup.py가 프라이빗 리포지터리에 도달할 수 있도록 업데이트해야 합니다. 구성 예시는 다음과 같습니다.

  1. install_requires 목록의 각 의존성에 대해 프라이빗 리포지터리를 가리키는 dependency_links 속성을 만들도록 setup.py를 업데이트합니다.

    install_requires=['pyparsing>=2.0.3'],
    dependency_links=['https://pypi.example.com/simple/pyparsing'],
    
  2. 리포지터리 URL에서 인증서를 가져와 프로젝트에 추가합니다.

    printf "\n" | openssl s_client -connect pypi.example.com:443 -servername pypi.example.com | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > internal.crt
    
  3. setup.py가 새로 내려받은 인증서를 가리키게 합니다.

    import setuptools.ssl_support
    setuptools.ssl_support.cert_paths = ['internal.crt']
    

Python (Pipenv)#

네트워크 연결이 제한된 환경에서 실행하는 경우 PIPENV_PYPI_MIRROR 변수를 구성해 프라이빗 PyPi 미러를 사용해야 합니다. 이 미러에는 기본 의존성과 개발 의존성이 모두 있어야 합니다.

variables:
  PIPENV_PYPI_MIRROR: https://pypi.example.com/simple

또는 프라이빗 레지스트리를 사용할 수 없으면 필요한 패키지를 Pipenv 가상 환경 캐시에 불러올 수 있습니다. 이 방법을 쓰려면 프로젝트가 Pipfile.lock을 리포지터리에 커밋해야 하며, 기본 패키지와 개발 패키지를 모두 캐시에 불러와야 합니다. 이를 구현하는 방법은 예시 python-pipenv 프로젝트를 참고합니다.

의존성 탐지#

의존성 스캔은 리포지터리에서 사용하는 언어를 자동으로 감지합니다. 감지된 언어와 일치하는 모든 분석기가 실행됩니다. 일반적으로 분석기 선택을 사용자 지정할 필요는 없습니다. 분석기를 지정하지 않으면 전체 선택을 자동으로 사용해 최상의 적용 범위를 확보하고, 더 이상 사용되지 않거나 제거될 때 조정할 필요도 없습니다. 다만 변수 DS_EXCLUDED_ANALYZERS를 사용해 선택을 재정의할 수 있습니다.

언어 감지는 CI job rules에 의존해 지원되는 의존성 파일을 감지합니다.

Java와 Python에서는 지원되는 의존성 파일이 감지되면 의존성 스캔이 프로젝트를 빌드하고 일부 Java 또는 Python 명령을 실행해 의존성 목록을 가져오려 시도합니다. 그 밖의 모든 프로젝트에서는 프로젝트를 먼저 빌드하지 않고도 잠금 파일을 파싱해 의존성 목록을 얻습니다.

모든 직접 의존성과 전이 의존성이 분석되며, 전이 의존성의 깊이에는 제한이 없습니다.

분석기#

의존성 스캔은 다음 공식 Gemnasium 기반 분석기를 지원합니다.

  • gemnasium
  • gemnasium-maven
  • gemnasium-python

분석기는 Docker 이미지로 게시되며, 의존성 스캔은 이 이미지를 사용해 분석마다 전용 컨테이너를 시작합니다. 사용자 지정 보안 스캐너를 통합할 수도 있습니다.

각 분석기는 Gemnasium의 새 버전이 릴리스될 때마다 업데이트됩니다.

분석기가 의존성 정보를 얻는 방법#

GitLab 분석기는 다음 두 가지 방법 중 하나로 의존성 정보를 얻습니다.

  1. 잠금 파일을 직접 파싱합니다.
  2. 패키지 관리자 또는 빌드 도구를 실행해 의존성 정보 파일을 생성한 다음 이를 파싱합니다.

잠금 파일을 파싱해 의존성 정보 얻기#

다음 패키지 관리자는 GitLab 분석기가 직접 파싱할 수 있는 잠금 파일을 사용합니다.

패키지 관리자 지원되는 파일 형식 버전 테스트된 패키지 관리자 버전
Bundler 해당 없음 1.17.3, 2.1.4
Composer 해당 없음 1.x
Conan 0.4 1.x
Go 해당 없음 1.x
NuGet v1, v2 4.9
npm v1, v2, v3 6.x, 7.x, 9.x
pnpm v5, v6, v9 7.x, 8.x 9.x
yarn 버전 1, 2, 3, 41 1.x, 2.x, 3.x
Poetry v1 1.x
uv v0.x 0.x

Footnotes:

  1. Yarn Berry에서는 다음 기능이 지원되지 않습니다.

    • 워크스페이스
    • yarn patch

    패치, 워크스페이스 또는 둘 다 포함한 Yarn 파일도 여전히 처리되지만 이 기능은 무시됩니다.

패키지 관리자를 실행해 파싱 가능한 파일을 생성하여 의존성 정보 얻기#

다음 패키지 관리자를 지원하기 위해 GitLab 분석기는 두 단계로 진행합니다.

  1. 패키지 관리자 또는 특정 태스크를 실행해 의존성 정보를 내보냅니다.
  2. 내보낸 의존성 정보를 파싱합니다.
패키지 관리자 사전 설치된 버전 테스트된 버전
sbt 1.6.2 1.1.6, 1.2.8, 1.3.12, 1.4.6, 1.5.8, 1.6.2, 1.7.3, 1.8.3, 1.9.6, 1.9.7
maven 3.9.8 3.9.81
Gradle 6.7.1, 7.6.4, 8.82 5.6, 6.7, 6.9, 7.6, 8.8
setuptools 70.3.0 >= 70.3.0
pip 24 24
Pipenv 2023.11.15 2023.11.153, 2023.11.15
Go 1.21 1.214

Footnotes:

  1. 이 테스트는 .tool-versions 파일에 지정된 maven 기본 버전을 사용합니다.
  2. Java 버전마다 필요한 Gradle 버전이 다릅니다. 앞의 표에 나열된 Gradle 버전은 분석기 이미지에 사전 설치되어 있습니다. 분석기가 사용하는 Gradle 버전은 프로젝트가 gradlew(Gradle 래퍼) 파일을 사용하는지에 따라 달라집니다.
    • 프로젝트가 gradlew 파일을 사용하지 않으면 분석기는 DS_JAVA_VERSION 변수에 지정된 Java 버전(기본 버전은 17)에 따라 사전 설치된 Gradle 버전 중 하나로 자동 전환합니다.

      Java 8과 11에서는 Gradle 6.7.1이 자동으로 선택되고, Java 17은 Gradle 7.6.4를, Java 21은 Gradle 8.8을 사용합니다.

    • 프로젝트가 gradlew 파일을 사용하면 분석기 이미지에 사전 설치된 Gradle 버전은 무시되고 gradlew 파일에 지정된 버전이 대신 사용됩니다.

  3. 이 테스트는 Pipfile.lock 파일이 발견되면 Gemnasium이 이 파일에 나열된 정확한 패키지 버전을 스캔하는 데 사용함을 확인합니다.
  4. go build의 구현 방식 때문에 Go 빌드 과정에는 네트워크 접근, go mod download로 미리 불러온 mod 캐시 또는 벤더링된 의존성이 필요합니다. 자세한 내용은 패키지와 의존성 컴파일에 대한 Go 문서를 참고합니다.

분석기가 트리거되는 방식#

GitLab은 리포지터리에 지원되는 파일이 있는지로 감지한 언어에 해당하는 분석기를 시작하기 위해 rules:exists를 사용합니다. 리포지터리 루트에서 최대 두 단계의 디렉터리까지 검색합니다. 예를 들어 리포지터리에 Gemfile, api/Gemfile, api/client/Gemfile 중 하나가 있으면 gemnasium-dependency_scanning job이 활성화되지만, 지원되는 의존성 파일이 api/v1/client/Gemfile뿐이면 활성화되지 않습니다.

여러 파일이 처리되는 방식#

Note

여러 파일을 스캔하는 중에 문제가 발생했다면 이 이슈에 댓글을 남겨 주십시오.

Python#

GitLab은 requirements 파일 또는 잠금 파일이 감지된 디렉터리에서 설치를 한 번만 실행합니다. 의존성은 감지된 첫 번째 파일에 대해서만 gemnasium-python이 분석합니다. 파일은 다음 순서로 검색합니다.

  1. Pip를 사용하는 프로젝트의 requirements.txt, requirements.pip 또는 requires.txt.
  2. Pipenv를 사용하는 프로젝트의 Pipfile 또는 Pipfile.lock.
  3. Poetry를 사용하는 프로젝트의 poetry.lock.
  4. Setuptools를 사용하는 프로젝트의 setup.py.

검색은 루트 디렉터리에서 시작하며, 루트 디렉터리에서 빌드를 찾지 못하면 하위 디렉터리로 이어집니다. 따라서 루트 디렉터리의 Poetry 잠금 파일이 하위 디렉터리의 Pipenv 파일보다 먼저 감지됩니다.

Java 및 Scala#

GitLab은 빌드 파일이 감지된 디렉터리에서 빌드를 한 번만 실행합니다. Gradle, Maven, sbt 빌드를 여러 개 포함하거나 이를 조합한 대규모 프로젝트에서는 gemnasium-maven이 감지된 첫 번째 빌드 파일에 대해서만 의존성을 분석합니다. 빌드 파일은 다음 순서로 검색합니다.

  1. 단일 또는 멀티 모듈 Maven 프로젝트의 pom.xml.
  2. 단일 또는 멀티 프로젝트 Gradle 빌드의 build.gradle 또는 build.gradle.kts.
  3. 단일 또는 멀티 프로젝트 sbt 빌드의 build.sbt.

검색은 루트 디렉터리에서 시작하며, 루트 디렉터리에서 빌드를 찾지 못하면 하위 디렉터리로 이어집니다. 따라서 루트 디렉터리의 sbt 빌드 파일이 하위 디렉터리의 Gradle 빌드 파일보다 먼저 감지됩니다. 멀티 모듈 Maven 프로젝트와 멀티 프로젝트 Gradle 및 sbt 빌드에서는 하위 모듈과 하위 프로젝트 파일이 상위 빌드 파일에 선언되어 있으면 분석됩니다.

JavaScript#

다음 분석기가 실행되며, 각 분석기는 여러 파일을 처리할 때 동작이 다릅니다.

  • Gemnasium

    여러 잠금 파일을 지원합니다.

  • Retire.js

    여러 잠금 파일을 지원하지 않습니다. 잠금 파일이 여러 개 있으면 Retire.js는 디렉터리 트리를 알파벳 순서로 순회하며 처음 발견한 잠금 파일을 분석합니다.

gemnasium 분석기는 JavaScript 프로젝트에서 벤더링된 라이브러리 (즉, 프로젝트에 커밋되었지만 패키지 관리자가 관리하지 않는 라이브러리)를 스캔합니다.

Go#

여러 파일이 지원됩니다. go.mod 파일이 감지되면 분석기는 최소 버전 선택(Minimal Version Selection)을 사용해 빌드 목록을 생성하려 시도합니다. 실패하면 분석기는 대신 go.mod 파일 안의 의존성을 파싱하려 시도합니다.

요구 사항으로, 의존성이 올바르게 관리되도록 go.mod 파일을 go mod tidy 명령으로 정리해야 합니다. 이 과정은 감지된 모든 go.mod 파일에 대해 반복됩니다.

PHP, C, C++, .NET, C#, Ruby, JavaScript#

이 언어들의 분석기는 여러 잠금 파일을 지원합니다.

추가 언어 지원#

추가 언어, 의존성 관리자, 의존성 파일에 대한 지원은 다음 이슈에서 추적합니다.

패키지 관리자 언어 지원되는 파일 스캔 도구 이슈
Poetry Python pyproject.toml Gemnasium GitLab#32774

경고#

모든 컨테이너는 최신 버전을 사용하고, 모든 패키지 관리자와 언어는 지원되는 최신 버전을 사용합니다. 이전 버전을 사용하면 지원되지 않는 버전이 더 이상 적극적인 보안 보고와 보안 수정의 백포트 혜택을 받지 못할 수 있으므로 보안 위험이 커집니다.

Gradle 프로젝트#

Gradle 프로젝트에서 HTML 의존성 보고서를 생성할 때 reports.html.destination 또는 reports.html.outputLocation 속성을 재정의하지 않습니다. 재정의하면 의존성 스캔이 올바르게 동작하지 않습니다.

Maven 프로젝트#

격리된 네트워크에서 중앙 리포지터리가 프라이빗 레지스트리(<mirror> 지시문으로 명시적으로 설정)인 경우 Maven 빌드가 gemnasium-maven-plugin 의존성을 찾지 못할 수 있습니다. Maven이 기본적으로 로컬 리포지터리(/root/.m2)를 검색하지 않고 중앙 리포지터리에서 가져오려 하기 때문에 발생하는 문제이며, 그 결과 누락된 의존성에 대한 오류가 발생합니다.

해결 방법#

이 문제를 해결하려면 settings.xml 파일에 <pluginRepositories> 섹션을 추가합니다. 그러면 Maven이 로컬 리포지터리에서 플러그인을 찾을 수 있습니다.

시작하기 전에 다음 사항을 고려합니다.

  • 이 해결 방법은 기본 Maven 중앙 리포지터리가 프라이빗 레지스트리로 미러링된 환경에만 해당합니다.
  • 이 해결 방법을 적용하면 Maven이 로컬 리포지터리에서 플러그인을 검색하며, 일부 환경에서는 보안에 영향을 줄 수 있습니다. 조직의 보안 정책에 부합하는지 확인합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

다음 단계에 따라 settings.xml 파일을 수정합니다.

  1. Maven settings.xml 파일을 찾습니다. 이 파일은 일반적으로 다음 위치 중 하나에 있습니다.

    • root 사용자의 경우 /root/.m2/settings.xml.
    • 일반 사용자의 경우 ~/.m2/settings.xml.
    • 전역 설정의 경우 ${maven.home}/conf/settings.xml.
  2. 파일에 기존 <pluginRepositories> 섹션이 있는지 확인합니다.

  3. <pluginRepositories> 섹션이 이미 있으면 그 안에 다음 <pluginRepository> 요소만 추가합니다. 없으면 <pluginRepositories> 섹션 전체를 추가합니다.

      <pluginRepositories>
        <pluginRepository>
            <id>local2</id>
            <name>local repository</name>
            <url>file:///root/.m2/repository/</url>
        </pluginRepository>
      </pluginRepositories>
    
  4. Maven 빌드 또는 의존성 스캔 과정을 다시 실행합니다.

Python 프로젝트#

PIP_EXTRA_INDEX_URL 환경 변수를 사용할 때는 CVE-2018-20225에 문서화된 악용 가능성 때문에 각별한 주의가 필요합니다.

Warning

pip(모든 버전)에서 사용자가 프라이빗 인덱스의 프라이빗 패키지를 받으려 했더라도 가장 높은 버전 번호의 버전을 설치하는 문제가 발견되었습니다. 이 문제는 PIP_EXTRA_INDEX_URL 옵션을 사용할 때만 영향을 주며, 악용하려면 해당 패키지가 공개 인덱스에 아직 존재하지 않아야 합니다(따라서 공격자가 임의의 버전 번호로 그곳에 패키지를 올릴 수 있습니다).

버전 번호 파싱#

경우에 따라 프로젝트 의존성의 버전이 보안 권고의 영향 범위에 속하는지 판단할 수 없습니다.

예를 들면 다음과 같습니다.

  • 버전을 알 수 없습니다.
  • 버전이 유효하지 않습니다.
  • 버전을 파싱하거나 범위와 비교하는 데 실패합니다.
  • 버전이 dev-master나 1.5.x 같은 브랜치입니다.
  • 비교 대상 버전이 모호합니다. 예를 들어 1.0.0-20241502는 1.0.0-2와 비교할 수 없는데, 한 버전은 타임스탬프를 포함하고 다른 버전은 포함하지 않기 때문입니다.

이런 경우 분석기는 해당 의존성을 건너뛰고 로그에 메시지를 출력합니다.

GitLab 분석기는 가정을 하지 않습니다. 가정은 오탐 또는 미탐을 낳을 수 있기 때문입니다. 논의는 이슈 442027을 참고합니다.

Swift 프로젝트 빌드#

Swift Package Manager(SPM)는 Swift 코드의 배포를 관리하는 공식 도구입니다. Swift 빌드 시스템과 통합되어 의존성을 내려받고 컴파일하고 링크하는 과정을 자동화합니다.

SPM으로 Swift 프로젝트를 빌드할 때는 다음 모범 사례를 따릅니다.

  1. Package.resolved 파일을 포함합니다.

    Package.resolved 파일은 의존성을 특정 버전으로 고정합니다. 환경 간 일관성을 보장하려면 이 파일을 항상 리포지터리에 커밋합니다.

    git add Package.resolved
    git commit -m "Add Package.resolved to lock dependencies"
    
  2. Swift 프로젝트를 빌드하려면 다음 명령을 사용합니다.

    # Update dependencies
    swift package update
    
    # Build the project
    swift build
    
  3. CI/CD를 구성하려면 .gitlab-ci.yml 파일에 다음 단계를 추가합니다.

    swift-build:
      stage: build
      script:
        - swift package update
        - swift build
    
  4. 선택 사항. 자체 서명 인증서를 사용하는 프라이빗 Swift 패키지 리포지터리를 사용한다면 프로젝트에 인증서를 추가하고 Swift가 이를 신뢰하도록 구성해야 할 수 있습니다.

    1. 인증서를 가져옵니다.

      echo | openssl s_client -servername your.repo.url -connect your.repo.url:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END
      CERTIFICATE-/p' > repo-cert.crt
      
    2. Swift 패키지 매니페스트(Package.swift)에 다음 줄을 추가합니다.

      import Foundation
      
      #if canImport(Security)
      import Security
      #endif
      
      extension Package {
          public static func addCustomCertificate() {
              guard let certPath = Bundle.module.path(forResource: "repo-cert", ofType: "crt") else {
                  fatalError("Certificate not found")
              }
              SecCertificateAddToSystemStore(SecCertificateCreateWithData(nil, try! Data(contentsOf: URL(fileURLWithPath: certPath)) as CFData)!)
          }
      }
      
      // Call this before defining your package
      Package.addCustomCertificate()
      

의존성이 올바르게 지정되고 자동으로 해석되도록 빌드 과정은 항상 깨끗한 환경에서 테스트합니다.

CocoaPods 프로젝트 빌드#

CocoaPods는 Swift 및 Objective-C Cocoa 프로젝트에서 널리 쓰이는 의존성 관리자입니다. iOS, macOS, watchOS, tvOS 프로젝트에서 외부 라이브러리를 관리하는 표준 형식을 제공합니다.

의존성 관리에 CocoaPods를 사용하는 프로젝트를 빌드할 때는 다음 모범 사례를 따릅니다.

  1. Podfile.lock 파일을 포함합니다.

    Podfile.lock 파일은 의존성을 특정 버전으로 고정하는 데 필수적입니다. 환경 간 일관성을 보장하려면 이 파일을 항상 리포지터리에 커밋합니다.

    git add Podfile.lock
    git commit -m "Add Podfile.lock to lock CocoaPods dependencies"
    
  2. 다음 중 하나로 프로젝트를 빌드할 수 있습니다.

    • xcodebuild 명령줄 도구:

      # Install CocoaPods dependencies
      pod install
      
      # Build the project
      xcodebuild -workspace YourWorkspace.xcworkspace -scheme YourScheme build
      
    • Xcode IDE:

      1. Xcode에서 .xcworkspace 파일을 엽니다.
      2. 대상 스킴을 선택합니다.
      3. Product > Build를 선택합니다. ⌘+B를 눌러도 됩니다.
    • iOS 및 Android 앱의 빌드와 릴리스를 자동화하는 도구인 fastlane:

      1. fastlane을 설치합니다.

        sudo gem install fastlane
        
      2. 프로젝트에서 fastlane을 구성합니다.

        fastlane init
        
      3. fastfile에 lane을 추가합니다.

        lane :build do
          cocoapods
          gym(scheme: "YourScheme")
        end
        
      4. 빌드를 실행합니다.

        fastlane build
        
    • 프로젝트가 CocoaPods와 Carthage를 모두 사용하면 Carthage로 의존성을 빌드할 수 있습니다.

      1. CocoaPods 의존성을 포함하는 Cartfile을 생성합니다.

      2. 다음을 실행합니다.

        carthage update --platform iOS
        
  3. 선호하는 방법에 따라 프로젝트를 빌드하도록 CI/CD를 구성합니다.

    예를 들어 xcodebuild를 사용하면 다음과 같습니다.

    cocoapods-build:
      stage: build
      script:
        - pod install
        - xcodebuild -workspace YourWorkspace.xcworkspace -scheme YourScheme build
    
  4. 선택 사항. 프라이빗 CocoaPods 리포지터리를 사용한다면 해당 리포지터리에 접근하도록 프로젝트를 구성해야 할 수 있습니다.

    1. 프라이빗 spec 리포지터리를 추가합니다.

      pod repo add REPO_NAME SOURCE_URL
      
    2. Podfile에 소스를 지정합니다.

      source 'https://github.com/CocoaPods/Specs.git'
      source 'SOURCE_URL'
      
  5. 선택 사항. 프라이빗 CocoaPods 리포지터리가 SSL을 사용한다면 SSL 인증서가 올바르게 구성되어 있는지 확인합니다.

    • 자체 서명 인증서를 사용한다면 시스템의 신뢰할 수 있는 인증서에 추가합니다. .netrc 파일에 SSL 구성을 지정할 수도 있습니다.

      machine your.private.repo.url
        login your_username
        password your_password
      
  6. Podfile을 업데이트한 후 pod install을 실행해 의존성을 설치하고 워크스페이스를 업데이트합니다.

모든 의존성이 올바르게 설치되고 워크스페이스가 업데이트되도록 Podfile을 업데이트한 후에는 항상 pod install을 실행합니다.

취약점 데이터베이스에 기여#

취약점을 찾으려면 GitLab advisory database에서 검색할 수 있습니다. 새 취약점을 제출할 수도 있습니다.

의존성 스캐닝

GitLab v19.4
Tier: Ultimate
Offering: GitLab Self-Managed
원문 보기

요약

Gemnasium 분석기 기반 의존성 스캔 기능은 GitLab 17.9에서 더 이상 사용되지 않으며(deprecated), GitLab 20.0에서 제거될 예정입니다. 의존성 스캔은 CI/CD 파이프라인에 통합되어 자동으로 실행되며, 애플리케이션 의존성의 보안 취약점을 식별합니다.

Warning

Gemnasium 분석기 기반 의존성 스캔 기능은 GitLab 17.9에서 더 이상 사용되지 않으며(deprecated), GitLab 20.0에서 제거될 예정입니다. 다만 제거 시점은 확정되지 않았으며, 필요에 따라 Gemnasium을 계속 사용할 수 있습니다. 자세한 내용은 에픽 15961을 참고합니다.

의존성 스캔은 CI/CD 파이프라인에 통합되어 자동으로 실행되며, 애플리케이션 의존성의 보안 취약점을 식별합니다. 브랜치를 병합하기 전에 스캔하면 머지 리퀘스트에서 보안 문제를 즉시 확인할 수 있습니다. 이를 통해 코드를 병합하기 전에 잠재적 취약점에 대해 충분한 정보를 바탕으로 결정을 내릴 수 있습니다.

기본적으로 의존성 스캔은 런타임, 개발, 전이(중첩) 의존성을 포함해 코드의 모든 의존성을 분석합니다. 필요에 따라 스캔에서 개발 의존성을 제외할 수 있습니다.

파이프라인 밖에서 의존성의 취약점을 스캔하려면 지속적 취약점 스캔을 참고합니다.

의존성 스캔 켜기#

다음 단계에 따라 프로젝트에서 의존성 스캔을 켭니다.

분석기를 사용 설정하려면 다음 중 하나를 수행합니다.

사전 구성된 머지 리퀘스트 사용#

이 방법은 .gitlab-ci.yml 파일에 의존성 스캔 템플릿을 포함한 머지 리퀘스트를 자동으로 준비합니다. 그런 다음 머지 리퀘스트를 병합하면 의존성 스캔이 사용 설정됩니다.

Note

이 방법은 기존 .gitlab-ci.yml 파일이 없거나 최소한의 구성 파일만 있을 때 가장 잘 동작합니다. GitLab 구성 파일이 복잡하면 파싱에 성공하지 못해 오류가 발생할 수 있습니다. 그 경우에는 수동 방법을 대신 사용합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.
  • .gitlab-ci.yml 파일에 test Stage가 있어야 합니다.
  • 자체 관리형 러너의 경우 docker 또는 kubernetes executor를 사용하는 GitLab Runner.
  • GitLab.com의 호스팅 러너는 이 구성이 기본적으로 사용 설정되어 있습니다.

의존성 스캔을 켜려면 다음을 수행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Secure > Security configuration을 선택합니다.
  3. Dependency Scanning 행에서 Configure with a merge request를 선택합니다.
  4. Create merge request를 선택합니다.
  5. 머지 리퀘스트를 검토한 다음 Merge를 선택합니다.

이제 파이프라인에 의존성 스캔 job이 포함됩니다.

.gitlab-ci.yml 파일 직접 편집#

이 방법은 기존 .gitlab-ci.yml 파일을 직접 편집해야 합니다. GitLab CI/CD 구성 파일이 복잡한 경우 이 방법을 사용합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.
  • .gitlab-ci.yml 파일에 test Stage가 있어야 합니다.
  • 자체 관리형 러너의 경우 docker 또는 kubernetes executor를 사용하는 GitLab Runner.
  • GitLab.com의 호스팅 러너는 이 구성이 기본적으로 사용 설정되어 있습니다.

의존성 스캔을 켜려면 다음을 수행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.

  2. 왼쪽 사이드바에서 Build > Pipeline editor를 선택합니다.

  3. .gitlab-ci.yml 파일이 없으면 Configure pipeline을 선택한 다음 예시 내용을 삭제합니다.

  4. 다음을 복사해 .gitlab-ci.yml 파일 맨 아래에 붙여넣습니다. include 줄이 이미 있으면 그 아래에 template 줄만 추가합니다.

    include:
      - template: Jobs/Dependency-Scanning.gitlab-ci.yml
    
  5. Validate 탭을 선택한 다음 Validate pipeline을 선택합니다.

    Simulation completed successfully 메시지가 표시되면 파일이 유효한 것입니다.

  6. Edit 탭을 선택합니다.

  7. 필드를 입력합니다. Branch 필드에는 기본 브랜치를 사용하지 않습니다.

  8. Start a new merge request with these changes 체크박스를 선택한 다음 Commit changes를 선택합니다.

  9. 표준 워크플로에 따라 필드를 입력한 다음 Create merge request를 선택합니다.

  10. 표준 워크플로에 따라 머지 리퀘스트를 검토하고 편집한 다음 Merge를 선택합니다.

이제 파이프라인에 의존성 스캔 job이 포함됩니다.

CI/CD 컴포넌트 사용#

Note

의존성 스캔 CI/CD 컴포넌트는 Android 프로젝트만 지원합니다.

CI/CD 컴포넌트를 사용해 애플리케이션의 의존성 스캔을 수행합니다. 방법은 해당 컴포넌트의 README 파일을 참고합니다.

사용 가능한 CI/CD 컴포넌트#

https://gitlab.com/explore/catalog/components/dependency-scanning을 참고합니다.

이 단계를 완료하면 다음을 할 수 있습니다.

결과 이해#

의존성 스캔 결과는 여러 형식으로 제공됩니다. 파이프라인 UI, 상세 스캔 보고서, 또는 스캔 중 생성되는 소프트웨어 자재 명세서(SBOM, Software Bill of Materials)에서 직접 확인할 수 있습니다.

파이프라인의 취약점 검토#

파이프라인에서 탐지된 취약점을 검토하고 머지 리퀘스트가 병합되기 전에 조치합니다.

사전 요구 사항:

  • 프로젝트의 Developer, Maintainer 또는 Owner 권한.

파이프라인에서 의존성 스캔 결과를 검토하려면 다음을 수행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 왼쪽 사이드바에서 Build > Pipelines를 선택합니다.
  3. 파이프라인을 선택합니다.
  4. Security 탭을 선택합니다.
  5. 취약점을 선택하면 다음을 포함한 세부 정보를 볼 수 있습니다.
    • Status: 취약점이 분류(triage)되었는지 또는 해결되었는지를 나타냅니다.
    • Description: 취약점의 원인, 잠재적 영향, 권장 해결 단계를 설명합니다.
    • Severity: 영향도에 따라 6단계로 분류됩니다. 심각도 수준에 대해 자세히 알아봅니다.
    • CVSS score: 심각도에 대응하는 수치 값을 제공합니다.
    • EPSS: 취약점이 실제로 악용될 가능성을 보여 줍니다.
    • Has Known Exploit (KEV): 해당 취약점이 악용된 적이 있음을 나타냅니다.
    • Project: 취약점이 식별된 프로젝트를 강조해 표시합니다.
    • Report type / Scanner: 출력 유형과 해당 출력을 생성한 스캐너를 설명합니다.
    • Reachable: 취약한 의존성이 코드에서 사용되는지 여부를 나타냅니다.
    • Scanner: 어떤 분석기가 취약점을 탐지했는지 식별합니다.
    • Location: 취약한 의존성이 있는 파일을 나타냅니다.
    • Links: 취약점이 여러 어드바이저리 데이터베이스에 등재되었다는 근거입니다.
    • Identifiers: CVE 식별자 등 취약점을 분류하는 데 사용되는 참조 목록입니다.

의존성 스캔 보고서#

의존성 스캔은 모든 취약점의 세부 정보를 담은 보고서를 출력합니다. 이 보고서는 내부적으로 처리되어 결과가 UI에 표시됩니다. 보고서는 의존성 스캔 job의 아티팩트로도 출력되며 이름은 gl-dependency-scanning-report.json이고, 항상 프로젝트의 루트에 생성됩니다.

의존성 스캔 보고서에 대한 자세한 내용은 의존성 스캔 보고서 스키마를 참고합니다.

CycloneDX 소프트웨어 자재 명세서#

의존성 스캔은 감지한 지원 대상 잠금 파일 또는 빌드 파일마다 CycloneDX 소프트웨어 자재 명세서(SBOM)를 출력합니다.

CycloneDX SBOM은 다음과 같습니다.

  • 이름은 gl-sbom-<package-type>-<package-manager>.cdx.json입니다.
  • 의존성 스캔 job의 job 아티팩트로 제공됩니다.
  • 감지된 잠금 파일 또는 빌드 파일과 같은 디렉터리에 저장됩니다.

예를 들어 프로젝트가 다음과 같은 구조라고 가정합니다.

.
├── ruby-project/
│   └── Gemfile.lock
├── ruby-project-2/
│   └── Gemfile.lock
├── php-project/
│   └── composer.lock
└── go-project/
    └── go.sum

이 경우 Gemnasium 스캐너는 다음 CycloneDX SBOM을 생성합니다.

.
├── 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
└── go-project/
    ├── go.sum
    └── gl-sbom-go-go.cdx.json

단계적 적용#

단일 프로젝트의 의존성 스캔 결과를 신뢰할 수 있게 되면 다른 프로젝트로 적용 범위를 넓힐 수 있습니다.

  • 강제 스캔 실행을 사용해 여러 그룹에 의존성 스캔 설정을 적용합니다.
  • 고유한 요구 사항이 있으면 SBOM을 사용하는 의존성 스캔을 오프라인 환경에서 실행할 수 있습니다.

지원되는 언어 및 패키지 관리자#

Note

의존성 스캔은 컴파일러와 인터프리터의 런타임 설치를 지원하지 않습니다.

의존성 스캔은 다음 언어와 의존성 관리자를 지원합니다.

언어 언어 버전 패키지 관리자 지원되는 파일 여러 파일 처리 여부
.NET 모든 버전 NuGet packages.lock.json Y
C#
C 모든 버전 Conan conan.lock Y
C++
Go 모든 버전 Go
  • go.sum
Y
Java 및 Kotlin 8 LTS, 11 LTS, 17 LTS, 또는 21 LTS1 Gradle2
  • build.gradle
  • build.gradle.kts
N
Maven6 pom.xml N
JavaScript 및 TypeScript 모든 버전 npm
  • package-lock.json
  • npm-shrinkwrap.json
Y
yarn yarn.lock Y
pnpm3 pnpm-lock.yaml Y
PHP 모든 버전 Composer composer.lock Y
Python 3.117 setuptools8 setup.py N
pip
  • requirements.txt
  • requirements.pip
  • requires.txt
N
Pipenv N
Poetry4 poetry.lock N
uv11 uv.lock Y
Ruby 모든 버전 Bundler
  • Gemfile.lock
  • gems.locked
Y
Scala 모든 버전 sbt5 build.sbt N
Swift 모든 버전 Swift Package Manager Package.resolved N
CocoaPods9 모든 버전 CocoaPods Podfile.lock N
Dart10 모든 버전 Pub pubspec.lock N

각주:

  1. sbt의 Java 21 LTS는 1.9.7 버전으로 제한됩니다. 더 많은 sbt 버전에 대한 지원은 이슈 430335에서 추적할 수 있습니다. FIPS 모드가 사용 설정되어 있으면 지원되지 않습니다.
  2. FIPS 모드가 사용 설정되어 있으면 Gradle은 지원되지 않습니다.
  3. pnpm 잠금 파일은 번들된 의존성을 저장하지 않으므로 보고되는 의존성이 npm 또는 yarn과 다를 수 있습니다.
  4. poetry.lock 파일이 없는 프로젝트에 대한 지원은 이슈 32774에서 추적합니다.
  5. sbt 1.0.x 지원은 GitLab 16.8에서 더 이상 사용되지 않게 되었고 GitLab 17.0에서 제거되었습니다.
  6. 3.8.8 미만 Maven 지원은 GitLab 16.9에서 더 이상 사용되지 않게 되었고 GitLab 17.0에서 제거되었습니다.
  7. 이전 Python 버전 지원은 GitLab 16.9에서 더 이상 사용되지 않게 되었고 GitLab 17.0에서 제거되었습니다.
  8. 설치 프로그램에 필요하므로 pip와 setuptools는 모두 보고서에서 제외됩니다.
  9. 권고 정보 없이 SBOM만 제공됩니다. 이슈 468764를 참고합니다.
  10. 라이선스 탐지는 지원되지 않습니다. 에픽 17037을 참고합니다.
  11. 잠금 파일에 같은 패키지에 대해 환경 마커가 다른 항목이 여러 개 있으면(예: Python <3.11용 numpy==2.2.6과 Python ≥3.11용 numpy==2.4.1) 첫 번째 항목만 파싱되어 보고됩니다.

지원되는 개발 의존성#

개발 의존성 탐지는 다음 언어와 패키지 관리자에서 지원됩니다.

언어 패키지 관리자 파일
C/C++/Fortran/Go/Python/R conda conda-lock.yml
Java Maven maven.graph.json
Java/Kotlin Gradle dependencies.lock, dependencies.direct.lock, gradle-html-dependency-report.js, gradle.lockfile
JavaScript/TypeScript npm package-lock.json, npm-shrinkwrap.json
JavaScript/TypeScript pnpm pnpm-lock.yaml
PHP Composer composer.lock
Python Pipenv Pipfile.lock
Python Poetry poetry.lock
Python uv uv.lock

머지 리퀘스트 파이프라인에서 job 실행#

머지 리퀘스트 파이프라인에서 보안 스캔 도구 사용을 참고합니다.

분석기 동작 사용자 지정#

의존성 스캔을 사용자 지정하려면 CI/CD 변수를 사용합니다.

Warning

GitLab 분석기의 모든 사용자 지정은 기본 브랜치에 병합하기 전에 머지 리퀘스트에서 테스트합니다. 그렇지 않으면 다수의 오탐을 포함해 예기치 않은 결과가 발생할 수 있습니다.

의존성 스캔 job 재정의#

job 정의를 재정의하려면(예: variables 또는 dependencies 같은 속성 변경), 재정의할 job과 같은 이름으로 새 job을 선언합니다. 이 새 job은 템플릿 포함(include) 뒤에 배치하고 그 아래에 필요한 추가 키를 지정합니다.

예를 들어 다음은 gemnasium 분석기의 취약한 의존성 자동 해결을 비활성화합니다.

include:
  - template: Jobs/Dependency-Scanning.gitlab-ci.yml

gemnasium-dependency_scanning:
  variables:
    DS_REMEDIATE: "false"

dependencies: [] 속성을 재정의하려면 앞에서 설명한 대로 이 속성을 대상으로 하는 재정의 job을 추가합니다.

include:
  - template: Jobs/Dependency-Scanning.gitlab-ci.yml

gemnasium-dependency_scanning:
  dependencies: ["build"]

사용 가능한 CI/CD 변수#

CI/CD 변수를 사용해 의존성 스캔 동작을 사용자 지정할 수 있습니다.

전역 분석기 설정#

다음 변수로 전역 의존성 스캔 설정을 구성할 수 있습니다.

CI/CD 변수 설명
ADDITIONAL_CA_CERT_BUNDLE 신뢰할 CA 인증서 번들입니다. 여기에 제공한 인증서 번들은 스캔 과정에서 git, yarn, npm 같은 다른 도구에서도 사용됩니다. 자세한 내용은 사용자 지정 TLS 인증 기관을 참고합니다.
DS_EXCLUDED_ANALYZERS 의존성 스캔에서 제외할 분석기를 이름으로 지정합니다. 자세한 내용은 분석기를 참고합니다.
DS_EXCLUDED_PATHS 경로를 기준으로 스캔에서 파일과 디렉터리를 제외합니다. 패턴을 쉼표로 구분한 목록입니다. 패턴은 glob(지원되는 패턴은 doublestar.Match 참고)이거나 파일 또는 폴더 경로(예: doc,spec)일 수 있습니다. 상위 디렉터리도 패턴과 일치합니다. 스캔이 실행되기 전에 적용되는 사전 필터입니다. 기본값: "spec, test, tests, tmp".
DS_IMAGE_SUFFIX 이미지 이름에 추가되는 접미사입니다. (GitLab 팀 구성원은 이 비공개 이슈에서 더 많은 정보를 볼 수 있습니다: https://gitlab.com/gitlab-org/gitlab/-/issues/354796). FIPS 모드가 사용 설정되면 자동으로 "-fips"로 설정됩니다.
DS_MAX_DEPTH 분석기가 스캔할 지원 대상 파일을 몇 단계 깊이의 디렉터리까지 검색할지 정의합니다. 값이 -1이면 깊이에 관계없이 모든 디렉터리를 스캔합니다. 기본값: 2.
SECURE_ANALYZERS_PREFIX 공식 기본 이미지를 제공하는 Docker 레지스트리(프록시)의 이름을 재정의합니다.

분석기별 설정#

다음 변수로 특정 의존성 스캔 분석기의 동작을 구성합니다.

CI/CD 변수 분석기 기본값 설명
GEMNASIUM_DB_LOCAL_PATH gemnasium /gemnasium-db 로컬 Gemnasium 데이터베이스의 경로입니다.
GEMNASIUM_DB_UPDATE_DISABLED gemnasium "false" gemnasium-db 어드바이저리 데이터베이스의 자동 업데이트를 비활성화합니다. 사용법은 GitLab 어드바이저리 데이터베이스 접근을 참고합니다.
GEMNASIUM_DB_REMOTE_URL gemnasium https://gitlab.com/gitlab-org/security-products/gemnasium-db.git GitLab 어드바이저리 데이터베이스를 가져올 리포지터리 URL입니다.
GEMNASIUM_DB_REF_NAME gemnasium master 원격 리포지터리 데이터베이스의 브랜치 이름입니다. GEMNASIUM_DB_REMOTE_URL이 필요합니다.
GEMNASIUM_IGNORED_SCOPES gemnasium 무시할 Maven 의존성 스코프를 쉼표로 구분한 목록입니다. 자세한 내용은 Maven 의존성 스코프 문서를 참고합니다.
DS_REMEDIATE gemnasium "true", FIPS 모드에서는 "false" 취약한 의존성의 자동 해결을 사용 설정합니다. FIPS 모드에서는 지원되지 않습니다.
DS_REMEDIATE_TIMEOUT gemnasium 5m 자동 해결의 제한 시간입니다.
GEMNASIUM_LIBRARY_SCAN_ENABLED gemnasium "true" 벤더링된 JavaScript 라이브러리(패키지 관리자가 관리하지 않는 라이브러리)의 취약점 탐지를 사용 설정합니다. 이 기능을 쓰려면 커밋에 JavaScript 잠금 파일이 있어야 하며, 없으면 의존성 스캔이 실행되지 않고 벤더링된 파일도 스캔되지 않습니다.
의존성 스캔은 Retire.js 스캐너를 사용해 제한된 범위의 취약점을 탐지합니다. 탐지되는 취약점에 대한 자세한 내용은 Retire.js 리포지터리를 참고합니다.
DS_INCLUDE_DEV_DEPENDENCIES gemnasium "true" "false"로 설정하면 개발 의존성과 그 취약점이 보고되지 않습니다. Composer, Maven, npm, pnpm, Pipenv 또는 Poetry를 사용하는 프로젝트만 지원됩니다.
GOOS gemnasium "linux" Go 코드를 컴파일할 대상 운영 체제입니다.
GOARCH gemnasium "amd64" Go 코드를 컴파일할 대상 프로세서의 아키텍처입니다.
GOFLAGS gemnasium go build 도구에 전달되는 플래그입니다.
GOPRIVATE gemnasium 소스에서 직접 가져올 glob 패턴과 접두사의 목록입니다. 자세한 내용은 Go 프라이빗 모듈 문서를 참고합니다.
DS_JAVA_VERSION gemnasium-maven 17 Java 버전입니다. 사용 가능한 버전: 8, 11, 17, 21.
MAVEN_CLI_OPTS gemnasium-maven "-DskipTests --batch-mode" 분석기가 maven에 전달하는 명령줄 인수의 목록입니다. 프라이빗 리포지터리 사용 예시를 참고합니다.
GRADLE_CLI_OPTS gemnasium-maven 분석기가 gradle에 전달하는 명령줄 인수의 목록입니다.
GRADLE_PLUGIN_INIT_PATH gemnasium-maven "gemnasium-init.gradle" Gradle 초기화 스크립트의 경로를 지정합니다. 호환성을 위해 초기화 스크립트에 allprojects { apply plugin: 'project-report' }가 포함되어야 합니다.
DS_GRADLE_RESOLUTION_POLICY gemnasium-maven "failed" Gradle 의존성 해석의 엄격도를 제어합니다. 부분 결과를 허용하려면 "none"을, 의존성 해석에 하나라도 실패하면 스캔을 실패 처리하려면 "failed"를 지정합니다.
SBT_CLI_OPTS gemnasium-maven 분석기가 sbt에 전달하는 명령줄 인수의 목록입니다.
PIP_INDEX_URL gemnasium-python https://pypi.org/simple Python Package Index의 기본 URL입니다.
PIP_EXTRA_INDEX_URL gemnasium-python PIP_INDEX_URL 외에 사용할 패키지 인덱스의 추가 URL 배열입니다. 쉼표로 구분합니다. Warning: 이 환경 변수를 사용할 때는 다음 보안 고려 사항을 읽어 봅니다.
PIP_REQUIREMENTS_FILE gemnasium-python 스캔할 Pip requirements 파일입니다. 경로가 아니라 파일 이름입니다. 이 환경 변수를 설정하면 지정한 파일만 스캔됩니다.
PIPENV_PYPI_MIRROR gemnasium-python 설정하면 Pipenv가 사용하는 PyPi 인덱스를 미러로 재정의합니다.
DS_PIP_VERSION gemnasium-python 특정 pip 버전(예: "19.3")의 설치를 강제합니다. 설정하지 않으면 Docker 이미지에 설치된 pip를 사용합니다.
DS_PIP_DEPENDENCY_PATH gemnasium-python Python pip 의존성을 불러올 경로입니다.

기타 변수#

앞의 표는 사용할 수 있는 모든 변수를 망라한 목록이 아닙니다. 이 표에는 지원되고 테스트된 GitLab 및 분석기 고유 변수가 모두 들어 있습니다. 환경 변수 같은 다른 많은 변수도 전달해서 올바르게 동작하게 할 수 있습니다. 이 목록은 방대하며 모두 문서화되어 있지는 않습니다.

예를 들어 GitLab 변수가 아닌 환경 변수 HTTPS_PROXY를 모든 의존성 스캔 job에 전달하려면 다음과 같이 .gitlab-ci.yml의 CI/CD 변수로 설정합니다.

variables:
  HTTPS_PROXY: "https://squid-proxy:3128"
Note

Gradle 프로젝트에서 프록시를 사용하려면 추가 변수를 설정해야 합니다.

또는 의존성 스캔 같은 특정 job에서만 사용할 수도 있습니다.

dependency_scanning:
  variables:
    HTTPS_PROXY: $HTTPS_PROXY

모든 변수를 테스트한 것은 아니므로 일부는 동작하고 일부는 동작하지 않을 수 있습니다. 동작하지 않는 변수가 필요하면 기능 요청을 제출하거나 해당 변수를 사용할 수 있도록 코드에 기여할 수 있습니다.

사용자 지정 TLS 인증 기관#

의존성 스캔에서는 분석기 컨테이너 이미지에 기본으로 포함된 인증서 대신 SSL/TLS 연결에 사용자 지정 TLS 인증서를 사용할 수 있습니다.

사용자 지정 인증 기관 지원은 다음 버전에서 도입되었습니다.

분석기 버전
gemnasium v2.8.0
gemnasium-maven v2.9.0
gemnasium-python v2.7.0

사용자 지정 TLS 인증 기관 사용#

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

사용자 지정 TLS 인증 기관을 사용하려면 다음을 수행합니다.

예를 들어 .gitlab-ci.yml 파일에서 인증서를 구성하려면 다음과 같이 합니다.

variables:
  ADDITIONAL_CA_CERT_BUNDLE: |
      -----BEGIN CERTIFICATE-----
      MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
      ...
      jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
      -----END CERTIFICATE-----

프라이빗 Maven 리포지터리로 인증#

의존성 분석기가 프라이빗 Maven 리포지터리로 인증할 수 있게 하려면 CI/CD 파이프라인에서 자격 증명을 구성해야 합니다. 인증하지 않으면 의존성 분석기가 프라이빗 의존성에 접근할 수 없어 스캔이 실패합니다.

Warning

자격 증명을 .gitlab-ci.yml 파일에 추가하지 않습니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

의존성 분석기가 프라이빗 Maven 리포지터리로 인증할 수 있게 하려면 다음을 수행합니다.

  1. MAVEN_CLI_OPTS라는 이름의 프로젝트 CI/CD 변수를 생성하고 값에 자격 증명이 포함되도록 설정합니다.

    예를 들어 설정 파일 이름이 mysettings.xml, 사용자 이름이 myuser, 비밀번호가 verysecret이라면 MAVEN_CLI_OPTS CI/CD 변수를 다음과 같이 설정합니다.

    --settings mysettings.xml -Drepository.password=verysecret -Drepository.user=myuser

  2. 서버 구성이 담긴 mysettings.xml Maven 설정 파일을 생성합니다. 파일 이름은 1단계에서 --settings 옵션에 지정한 값과 일치해야 합니다.

    <!-- mysettings.xml -->
    <settings>
        ...
        <servers>
            <server>
                <id>private_server</id>
                <username>${repository.user}</username>
                <password>${repository.password}</password>
            </server>
        </servers>
    </settings>
    

FIPS 지원 이미지#

GitLab은 Gemnasium 이미지의 FIPS 지원 Red Hat UBI 버전도 제공합니다. GitLab 인스턴스에서 FIPS 모드가 사용 설정되면 Gemnasium 스캔 job은 FIPS 지원 이미지를 자동으로 사용합니다. FIPS 지원 이미지로 직접 전환하려면 변수 DS_IMAGE_SUFFIX를 "-fips"로 설정합니다.

FIPS 모드에서는 Gradle 프로젝트의 의존성 스캔과 Yarn 프로젝트의 자동 해결이 지원되지 않습니다.

FIPS 지원 이미지는 RedHat의 UBI micro를 기반으로 합니다. 이 이미지에는 dnf나 microdnf 같은 패키지 관리자가 없으므로 런타임에 시스템 패키지를 설치할 수 없습니다.

오프라인 환경#

인터넷을 통한 외부 리소스 접근이 제한적이거나 차단되었거나 간헐적인 환경의 인스턴스에서는 의존성 스캔 job이 성공적으로 실행되도록 일부 조정이 필요합니다. 자세한 내용은 오프라인 환경을 참고합니다.

사전 요구 사항:

분석기 이미지의 로컬 사본#

모든 지원되는 언어 및 프레임워크에서 의존성 스캔을 사용하려면 다음을 수행합니다.

  1. registry.gitlab.com의 다음 기본 의존성 스캔 분석기 이미지를 로컬 Docker 컨테이너 레지스트리로 가져옵니다.

    registry.gitlab.com/security-products/gemnasium:6
    registry.gitlab.com/security-products/gemnasium:6-fips
    registry.gitlab.com/security-products/gemnasium-maven:6
    registry.gitlab.com/security-products/gemnasium-maven:6-fips
    registry.gitlab.com/security-products/gemnasium-python:6
    registry.gitlab.com/security-products/gemnasium-python:6-fips
    

    Docker 이미지를 로컬 오프라인 Docker 레지스트리로 가져오는 절차는 네트워크 보안 정책에 따라 다릅니다. 외부 리소스를 가져오거나 일시적으로 접근할 수 있는 허용되고 승인된 절차를 IT 담당자와 상의합니다. 이 스캐너는 새 정의로 주기적으로 업데이트되므로 정기적으로 내려받는 것이 좋을 수 있습니다.

  2. 로컬 분석기를 사용하도록 GitLab CI/CD를 구성합니다.

    CI/CD 변수 SECURE_ANALYZERS_PREFIX의 값을 로컬 Docker 레지스트리로 설정합니다. 이 예시에서는 docker-registry.example.com입니다.

    include:
      - template: Jobs/Dependency-Scanning.gitlab-ci.yml
    
    variables:
      SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
    

GitLab 어드바이저리 데이터베이스 접근#

GitLab 어드바이저리 데이터베이스는 gemnasium, gemnasium-maven, gemnasium-python 분석기가 사용하는 취약점 데이터의 원천입니다. 이 분석기의 Docker 이미지에는 데이터베이스의 클론이 포함되어 있습니다. 분석기가 최신 취약점 데이터를 사용하도록 스캔을 시작하기 전에 클론이 데이터베이스와 동기화됩니다.

오프라인 환경에서는 GitLab 어드바이저리 데이터베이스의 기본 호스트에 접근할 수 없습니다. 대신 GitLab 러너가 접근할 수 있는 곳에 데이터베이스를 호스팅해야 합니다. 또한 원하는 일정에 따라 데이터베이스를 직접 업데이트해야 합니다.

데이터베이스를 호스팅하는 방법은 다음과 같습니다.

GitLab 어드바이저리 데이터베이스의 클론 사용#

GitLab 어드바이저리 데이터베이스의 클론을 사용하는 방법이 가장 효율적이므로 권장됩니다.

GitLab 어드바이저리 데이터베이스의 클론을 호스팅하려면 다음을 수행합니다.

  1. GitLab 러너에서 HTTP로 접근할 수 있는 호스트에 GitLab 어드바이저리 데이터베이스를 클론합니다.
  2. .gitlab-ci.yml 파일에서 CI/CD 변수 GEMNASIUM_DB_REMOTE_URL의 값을 Git 리포지터리의 URL로 설정합니다.

예를 들면 다음과 같습니다.

variables:
  GEMNASIUM_DB_REMOTE_URL: https://users-own-copy.example.com/gemnasium-db.git
GitLab 어드바이저리 데이터베이스의 사본 사용#

GitLab 어드바이저리 데이터베이스의 사본을 사용하려면 분석기가 내려받는 아카이브 파일을 호스팅해야 합니다.

GitLab 어드바이저리 데이터베이스의 사본을 사용하려면 다음을 수행합니다.

  1. GitLab 러너에서 HTTP로 접근할 수 있는 호스트에 GitLab 어드바이저리 데이터베이스의 아카이브를 내려받습니다. 아카이브는 다음 위치에 있습니다. https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/archive/master/gemnasium-db-master.tar.gz.

  2. .gitlab-ci.yml 파일을 업데이트합니다.

    • 데이터베이스의 로컬 사본을 사용하도록 CI/CD 변수 GEMNASIUM_DB_LOCAL_PATH를 설정합니다.
    • 데이터베이스 업데이트를 비활성화하도록 CI/CD 변수 GEMNASIUM_DB_UPDATE_DISABLED를 설정합니다.
    • 스캔이 시작되기 전에 어드바이저리 데이터베이스를 내려받아 압축을 풉니다.
    variables:
      GEMNASIUM_DB_LOCAL_PATH: ./gemnasium-db-local
      GEMNASIUM_DB_UPDATE_DISABLED: "true"
    
    dependency_scanning:
      before_script:
        - wget https://local.example.com/gemnasium_db.tar.gz
        - mkdir -p $GEMNASIUM_DB_LOCAL_PATH
        - tar -xzvf gemnasium_db.tar.gz --strip-components=1 -C $GEMNASIUM_DB_LOCAL_PATH
    

Gradle 프로젝트에서 프록시 사용#

Gradle 래퍼 스크립트는 HTTP(S)_PROXY 환경 변수를 읽지 않습니다. 자세한 내용은 Gradle 이슈 11065를 참고합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

Gradle 래퍼 스크립트가 프록시를 사용하게 하려면 다음을 수행합니다.

  • GRADLE_CLI_OPTS CI/CD 변수로 프록시 옵션을 지정합니다.

    variables:
      GRADLE_CLI_OPTS: "-Dhttps.proxyHost=squid-proxy -Dhttps.proxyPort=3128 -Dhttp.proxyHost=squid-proxy -Dhttp.proxyPort=3128 -Dhttp.nonProxyHosts=localhost"
    

Maven 프로젝트에서 프록시 사용#

Maven은 HTTP(S)_PROXY 환경 변수를 읽지 않습니다. 대신 Maven 설정 파일을 사용해야 합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

Maven 의존성 스캐너가 프록시를 사용하도록 구성하려면 다음을 수행합니다.

  1. 프로젝트의 리포지터리에 mysettings.xml 파일을 생성합니다. 그 파일에서 Maven 프록시 설정을 구성합니다.

    프록시 구성을 지정하는 방법은 Maven 문서를 참고합니다.

  2. 프로젝트의 .gitlab-ci.yml 파일에서 MAVEN_CLI_OPTS CI/CD 변수를 정의해 설정 파일 mysettings.xml을 참조하게 합니다.

    variables:
      MAVEN_CLI_OPTS: "--settings mysettings.xml"
    

언어 및 패키지 관리자별 설정#

특정 언어와 패키지 관리자를 구성하는 방법은 다음 절을 참고합니다.

Python (pip)#

분석기를 실행하기 전에 Python 패키지를 설치해야 하면 스캔 job의 before_script에서 pip install --user를 사용해야 합니다. --user 플래그를 사용하면 프로젝트 의존성이 사용자 디렉터리에 설치됩니다. --user 옵션을 전달하지 않으면 패키지가 전역으로 설치되어 스캔되지 않으며 프로젝트 의존성을 나열할 때도 표시되지 않습니다.

Python (setuptools)#

분석기를 실행하기 전에 Python 패키지를 설치해야 하면 스캔 job의 before_script에서 python setup.py install --user를 사용해야 합니다. --user 플래그를 사용하면 프로젝트 의존성이 사용자 디렉터리에 설치됩니다. --user 옵션을 전달하지 않으면 패키지가 전역으로 설치되어 스캔되지 않으며 프로젝트 의존성을 나열할 때도 표시되지 않습니다.

프라이빗 PyPi 리포지터리에 자체 서명 인증서를 사용하는 경우 (앞의 .gitlab-ci.yml 템플릿 외에는) 추가 job 구성이 필요하지 않습니다. 다만 setup.py가 프라이빗 리포지터리에 도달할 수 있도록 업데이트해야 합니다. 구성 예시는 다음과 같습니다.

  1. install_requires 목록의 각 의존성에 대해 프라이빗 리포지터리를 가리키는 dependency_links 속성을 만들도록 setup.py를 업데이트합니다.

    install_requires=['pyparsing>=2.0.3'],
    dependency_links=['https://pypi.example.com/simple/pyparsing'],
    
  2. 리포지터리 URL에서 인증서를 가져와 프로젝트에 추가합니다.

    printf "\n" | openssl s_client -connect pypi.example.com:443 -servername pypi.example.com | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > internal.crt
    
  3. setup.py가 새로 내려받은 인증서를 가리키게 합니다.

    import setuptools.ssl_support
    setuptools.ssl_support.cert_paths = ['internal.crt']
    

Python (Pipenv)#

네트워크 연결이 제한된 환경에서 실행하는 경우 PIPENV_PYPI_MIRROR 변수를 구성해 프라이빗 PyPi 미러를 사용해야 합니다. 이 미러에는 기본 의존성과 개발 의존성이 모두 있어야 합니다.

variables:
  PIPENV_PYPI_MIRROR: https://pypi.example.com/simple

또는 프라이빗 레지스트리를 사용할 수 없으면 필요한 패키지를 Pipenv 가상 환경 캐시에 불러올 수 있습니다. 이 방법을 쓰려면 프로젝트가 Pipfile.lock을 리포지터리에 커밋해야 하며, 기본 패키지와 개발 패키지를 모두 캐시에 불러와야 합니다. 이를 구현하는 방법은 예시 python-pipenv 프로젝트를 참고합니다.

의존성 탐지#

의존성 스캔은 리포지터리에서 사용하는 언어를 자동으로 감지합니다. 감지된 언어와 일치하는 모든 분석기가 실행됩니다. 일반적으로 분석기 선택을 사용자 지정할 필요는 없습니다. 분석기를 지정하지 않으면 전체 선택을 자동으로 사용해 최상의 적용 범위를 확보하고, 더 이상 사용되지 않거나 제거될 때 조정할 필요도 없습니다. 다만 변수 DS_EXCLUDED_ANALYZERS를 사용해 선택을 재정의할 수 있습니다.

언어 감지는 CI job rules에 의존해 지원되는 의존성 파일을 감지합니다.

Java와 Python에서는 지원되는 의존성 파일이 감지되면 의존성 스캔이 프로젝트를 빌드하고 일부 Java 또는 Python 명령을 실행해 의존성 목록을 가져오려 시도합니다. 그 밖의 모든 프로젝트에서는 프로젝트를 먼저 빌드하지 않고도 잠금 파일을 파싱해 의존성 목록을 얻습니다.

모든 직접 의존성과 전이 의존성이 분석되며, 전이 의존성의 깊이에는 제한이 없습니다.

분석기#

의존성 스캔은 다음 공식 Gemnasium 기반 분석기를 지원합니다.

  • gemnasium
  • gemnasium-maven
  • gemnasium-python

분석기는 Docker 이미지로 게시되며, 의존성 스캔은 이 이미지를 사용해 분석마다 전용 컨테이너를 시작합니다. 사용자 지정 보안 스캐너를 통합할 수도 있습니다.

각 분석기는 Gemnasium의 새 버전이 릴리스될 때마다 업데이트됩니다.

분석기가 의존성 정보를 얻는 방법#

GitLab 분석기는 다음 두 가지 방법 중 하나로 의존성 정보를 얻습니다.

  1. 잠금 파일을 직접 파싱합니다.
  2. 패키지 관리자 또는 빌드 도구를 실행해 의존성 정보 파일을 생성한 다음 이를 파싱합니다.

잠금 파일을 파싱해 의존성 정보 얻기#

다음 패키지 관리자는 GitLab 분석기가 직접 파싱할 수 있는 잠금 파일을 사용합니다.

패키지 관리자 지원되는 파일 형식 버전 테스트된 패키지 관리자 버전
Bundler 해당 없음 1.17.3, 2.1.4
Composer 해당 없음 1.x
Conan 0.4 1.x
Go 해당 없음 1.x
NuGet v1, v2 4.9
npm v1, v2, v3 6.x, 7.x, 9.x
pnpm v5, v6, v9 7.x, 8.x 9.x
yarn 버전 1, 2, 3, 41 1.x, 2.x, 3.x
Poetry v1 1.x
uv v0.x 0.x

Footnotes:

  1. Yarn Berry에서는 다음 기능이 지원되지 않습니다.

    • 워크스페이스
    • yarn patch

    패치, 워크스페이스 또는 둘 다 포함한 Yarn 파일도 여전히 처리되지만 이 기능은 무시됩니다.

패키지 관리자를 실행해 파싱 가능한 파일을 생성하여 의존성 정보 얻기#

다음 패키지 관리자를 지원하기 위해 GitLab 분석기는 두 단계로 진행합니다.

  1. 패키지 관리자 또는 특정 태스크를 실행해 의존성 정보를 내보냅니다.
  2. 내보낸 의존성 정보를 파싱합니다.
패키지 관리자 사전 설치된 버전 테스트된 버전
sbt 1.6.2 1.1.6, 1.2.8, 1.3.12, 1.4.6, 1.5.8, 1.6.2, 1.7.3, 1.8.3, 1.9.6, 1.9.7
maven 3.9.8 3.9.81
Gradle 6.7.1, 7.6.4, 8.82 5.6, 6.7, 6.9, 7.6, 8.8
setuptools 70.3.0 >= 70.3.0
pip 24 24
Pipenv 2023.11.15 2023.11.153, 2023.11.15
Go 1.21 1.214

Footnotes:

  1. 이 테스트는 .tool-versions 파일에 지정된 maven 기본 버전을 사용합니다.
  2. Java 버전마다 필요한 Gradle 버전이 다릅니다. 앞의 표에 나열된 Gradle 버전은 분석기 이미지에 사전 설치되어 있습니다. 분석기가 사용하는 Gradle 버전은 프로젝트가 gradlew(Gradle 래퍼) 파일을 사용하는지에 따라 달라집니다.
    • 프로젝트가 gradlew 파일을 사용하지 않으면 분석기는 DS_JAVA_VERSION 변수에 지정된 Java 버전(기본 버전은 17)에 따라 사전 설치된 Gradle 버전 중 하나로 자동 전환합니다.

      Java 8과 11에서는 Gradle 6.7.1이 자동으로 선택되고, Java 17은 Gradle 7.6.4를, Java 21은 Gradle 8.8을 사용합니다.

    • 프로젝트가 gradlew 파일을 사용하면 분석기 이미지에 사전 설치된 Gradle 버전은 무시되고 gradlew 파일에 지정된 버전이 대신 사용됩니다.

  3. 이 테스트는 Pipfile.lock 파일이 발견되면 Gemnasium이 이 파일에 나열된 정확한 패키지 버전을 스캔하는 데 사용함을 확인합니다.
  4. go build의 구현 방식 때문에 Go 빌드 과정에는 네트워크 접근, go mod download로 미리 불러온 mod 캐시 또는 벤더링된 의존성이 필요합니다. 자세한 내용은 패키지와 의존성 컴파일에 대한 Go 문서를 참고합니다.

분석기가 트리거되는 방식#

GitLab은 리포지터리에 지원되는 파일이 있는지로 감지한 언어에 해당하는 분석기를 시작하기 위해 rules:exists를 사용합니다. 리포지터리 루트에서 최대 두 단계의 디렉터리까지 검색합니다. 예를 들어 리포지터리에 Gemfile, api/Gemfile, api/client/Gemfile 중 하나가 있으면 gemnasium-dependency_scanning job이 활성화되지만, 지원되는 의존성 파일이 api/v1/client/Gemfile뿐이면 활성화되지 않습니다.

여러 파일이 처리되는 방식#

Note

여러 파일을 스캔하는 중에 문제가 발생했다면 이 이슈에 댓글을 남겨 주십시오.

Python#

GitLab은 requirements 파일 또는 잠금 파일이 감지된 디렉터리에서 설치를 한 번만 실행합니다. 의존성은 감지된 첫 번째 파일에 대해서만 gemnasium-python이 분석합니다. 파일은 다음 순서로 검색합니다.

  1. Pip를 사용하는 프로젝트의 requirements.txt, requirements.pip 또는 requires.txt.
  2. Pipenv를 사용하는 프로젝트의 Pipfile 또는 Pipfile.lock.
  3. Poetry를 사용하는 프로젝트의 poetry.lock.
  4. Setuptools를 사용하는 프로젝트의 setup.py.

검색은 루트 디렉터리에서 시작하며, 루트 디렉터리에서 빌드를 찾지 못하면 하위 디렉터리로 이어집니다. 따라서 루트 디렉터리의 Poetry 잠금 파일이 하위 디렉터리의 Pipenv 파일보다 먼저 감지됩니다.

Java 및 Scala#

GitLab은 빌드 파일이 감지된 디렉터리에서 빌드를 한 번만 실행합니다. Gradle, Maven, sbt 빌드를 여러 개 포함하거나 이를 조합한 대규모 프로젝트에서는 gemnasium-maven이 감지된 첫 번째 빌드 파일에 대해서만 의존성을 분석합니다. 빌드 파일은 다음 순서로 검색합니다.

  1. 단일 또는 멀티 모듈 Maven 프로젝트의 pom.xml.
  2. 단일 또는 멀티 프로젝트 Gradle 빌드의 build.gradle 또는 build.gradle.kts.
  3. 단일 또는 멀티 프로젝트 sbt 빌드의 build.sbt.

검색은 루트 디렉터리에서 시작하며, 루트 디렉터리에서 빌드를 찾지 못하면 하위 디렉터리로 이어집니다. 따라서 루트 디렉터리의 sbt 빌드 파일이 하위 디렉터리의 Gradle 빌드 파일보다 먼저 감지됩니다. 멀티 모듈 Maven 프로젝트와 멀티 프로젝트 Gradle 및 sbt 빌드에서는 하위 모듈과 하위 프로젝트 파일이 상위 빌드 파일에 선언되어 있으면 분석됩니다.

JavaScript#

다음 분석기가 실행되며, 각 분석기는 여러 파일을 처리할 때 동작이 다릅니다.

  • Gemnasium

    여러 잠금 파일을 지원합니다.

  • Retire.js

    여러 잠금 파일을 지원하지 않습니다. 잠금 파일이 여러 개 있으면 Retire.js는 디렉터리 트리를 알파벳 순서로 순회하며 처음 발견한 잠금 파일을 분석합니다.

gemnasium 분석기는 JavaScript 프로젝트에서 벤더링된 라이브러리 (즉, 프로젝트에 커밋되었지만 패키지 관리자가 관리하지 않는 라이브러리)를 스캔합니다.

Go#

여러 파일이 지원됩니다. go.mod 파일이 감지되면 분석기는 최소 버전 선택(Minimal Version Selection)을 사용해 빌드 목록을 생성하려 시도합니다. 실패하면 분석기는 대신 go.mod 파일 안의 의존성을 파싱하려 시도합니다.

요구 사항으로, 의존성이 올바르게 관리되도록 go.mod 파일을 go mod tidy 명령으로 정리해야 합니다. 이 과정은 감지된 모든 go.mod 파일에 대해 반복됩니다.

PHP, C, C++, .NET, C#, Ruby, JavaScript#

이 언어들의 분석기는 여러 잠금 파일을 지원합니다.

추가 언어 지원#

추가 언어, 의존성 관리자, 의존성 파일에 대한 지원은 다음 이슈에서 추적합니다.

패키지 관리자 언어 지원되는 파일 스캔 도구 이슈
Poetry Python pyproject.toml Gemnasium GitLab#32774

경고#

모든 컨테이너는 최신 버전을 사용하고, 모든 패키지 관리자와 언어는 지원되는 최신 버전을 사용합니다. 이전 버전을 사용하면 지원되지 않는 버전이 더 이상 적극적인 보안 보고와 보안 수정의 백포트 혜택을 받지 못할 수 있으므로 보안 위험이 커집니다.

Gradle 프로젝트#

Gradle 프로젝트에서 HTML 의존성 보고서를 생성할 때 reports.html.destination 또는 reports.html.outputLocation 속성을 재정의하지 않습니다. 재정의하면 의존성 스캔이 올바르게 동작하지 않습니다.

Maven 프로젝트#

격리된 네트워크에서 중앙 리포지터리가 프라이빗 레지스트리(<mirror> 지시문으로 명시적으로 설정)인 경우 Maven 빌드가 gemnasium-maven-plugin 의존성을 찾지 못할 수 있습니다. Maven이 기본적으로 로컬 리포지터리(/root/.m2)를 검색하지 않고 중앙 리포지터리에서 가져오려 하기 때문에 발생하는 문제이며, 그 결과 누락된 의존성에 대한 오류가 발생합니다.

해결 방법#

이 문제를 해결하려면 settings.xml 파일에 <pluginRepositories> 섹션을 추가합니다. 그러면 Maven이 로컬 리포지터리에서 플러그인을 찾을 수 있습니다.

시작하기 전에 다음 사항을 고려합니다.

  • 이 해결 방법은 기본 Maven 중앙 리포지터리가 프라이빗 레지스트리로 미러링된 환경에만 해당합니다.
  • 이 해결 방법을 적용하면 Maven이 로컬 리포지터리에서 플러그인을 검색하며, 일부 환경에서는 보안에 영향을 줄 수 있습니다. 조직의 보안 정책에 부합하는지 확인합니다.

사전 요구 사항:

  • 프로젝트의 Maintainer 또는 Owner 권한.

다음 단계에 따라 settings.xml 파일을 수정합니다.

  1. Maven settings.xml 파일을 찾습니다. 이 파일은 일반적으로 다음 위치 중 하나에 있습니다.

    • root 사용자의 경우 /root/.m2/settings.xml.
    • 일반 사용자의 경우 ~/.m2/settings.xml.
    • 전역 설정의 경우 ${maven.home}/conf/settings.xml.
  2. 파일에 기존 <pluginRepositories> 섹션이 있는지 확인합니다.

  3. <pluginRepositories> 섹션이 이미 있으면 그 안에 다음 <pluginRepository> 요소만 추가합니다. 없으면 <pluginRepositories> 섹션 전체를 추가합니다.

      <pluginRepositories>
        <pluginRepository>
            <id>local2</id>
            <name>local repository</name>
            <url>file:///root/.m2/repository/</url>
        </pluginRepository>
      </pluginRepositories>
    
  4. Maven 빌드 또는 의존성 스캔 과정을 다시 실행합니다.

Python 프로젝트#

PIP_EXTRA_INDEX_URL 환경 변수를 사용할 때는 CVE-2018-20225에 문서화된 악용 가능성 때문에 각별한 주의가 필요합니다.

Warning

pip(모든 버전)에서 사용자가 프라이빗 인덱스의 프라이빗 패키지를 받으려 했더라도 가장 높은 버전 번호의 버전을 설치하는 문제가 발견되었습니다. 이 문제는 PIP_EXTRA_INDEX_URL 옵션을 사용할 때만 영향을 주며, 악용하려면 해당 패키지가 공개 인덱스에 아직 존재하지 않아야 합니다(따라서 공격자가 임의의 버전 번호로 그곳에 패키지를 올릴 수 있습니다).

버전 번호 파싱#

경우에 따라 프로젝트 의존성의 버전이 보안 권고의 영향 범위에 속하는지 판단할 수 없습니다.

예를 들면 다음과 같습니다.

  • 버전을 알 수 없습니다.
  • 버전이 유효하지 않습니다.
  • 버전을 파싱하거나 범위와 비교하는 데 실패합니다.
  • 버전이 dev-master나 1.5.x 같은 브랜치입니다.
  • 비교 대상 버전이 모호합니다. 예를 들어 1.0.0-20241502는 1.0.0-2와 비교할 수 없는데, 한 버전은 타임스탬프를 포함하고 다른 버전은 포함하지 않기 때문입니다.

이런 경우 분석기는 해당 의존성을 건너뛰고 로그에 메시지를 출력합니다.

GitLab 분석기는 가정을 하지 않습니다. 가정은 오탐 또는 미탐을 낳을 수 있기 때문입니다. 논의는 이슈 442027을 참고합니다.

Swift 프로젝트 빌드#

Swift Package Manager(SPM)는 Swift 코드의 배포를 관리하는 공식 도구입니다. Swift 빌드 시스템과 통합되어 의존성을 내려받고 컴파일하고 링크하는 과정을 자동화합니다.

SPM으로 Swift 프로젝트를 빌드할 때는 다음 모범 사례를 따릅니다.

  1. Package.resolved 파일을 포함합니다.

    Package.resolved 파일은 의존성을 특정 버전으로 고정합니다. 환경 간 일관성을 보장하려면 이 파일을 항상 리포지터리에 커밋합니다.

    git add Package.resolved
    git commit -m "Add Package.resolved to lock dependencies"
    
  2. Swift 프로젝트를 빌드하려면 다음 명령을 사용합니다.

    # Update dependencies
    swift package update
    
    # Build the project
    swift build
    
  3. CI/CD를 구성하려면 .gitlab-ci.yml 파일에 다음 단계를 추가합니다.

    swift-build:
      stage: build
      script:
        - swift package update
        - swift build
    
  4. 선택 사항. 자체 서명 인증서를 사용하는 프라이빗 Swift 패키지 리포지터리를 사용한다면 프로젝트에 인증서를 추가하고 Swift가 이를 신뢰하도록 구성해야 할 수 있습니다.

    1. 인증서를 가져옵니다.

      echo | openssl s_client -servername your.repo.url -connect your.repo.url:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END
      CERTIFICATE-/p' > repo-cert.crt
      
    2. Swift 패키지 매니페스트(Package.swift)에 다음 줄을 추가합니다.

      import Foundation
      
      #if canImport(Security)
      import Security
      #endif
      
      extension Package {
          public static func addCustomCertificate() {
              guard let certPath = Bundle.module.path(forResource: "repo-cert", ofType: "crt") else {
                  fatalError("Certificate not found")
              }
              SecCertificateAddToSystemStore(SecCertificateCreateWithData(nil, try! Data(contentsOf: URL(fileURLWithPath: certPath)) as CFData)!)
          }
      }
      
      // Call this before defining your package
      Package.addCustomCertificate()
      

의존성이 올바르게 지정되고 자동으로 해석되도록 빌드 과정은 항상 깨끗한 환경에서 테스트합니다.

CocoaPods 프로젝트 빌드#

CocoaPods는 Swift 및 Objective-C Cocoa 프로젝트에서 널리 쓰이는 의존성 관리자입니다. iOS, macOS, watchOS, tvOS 프로젝트에서 외부 라이브러리를 관리하는 표준 형식을 제공합니다.

의존성 관리에 CocoaPods를 사용하는 프로젝트를 빌드할 때는 다음 모범 사례를 따릅니다.

  1. Podfile.lock 파일을 포함합니다.

    Podfile.lock 파일은 의존성을 특정 버전으로 고정하는 데 필수적입니다. 환경 간 일관성을 보장하려면 이 파일을 항상 리포지터리에 커밋합니다.

    git add Podfile.lock
    git commit -m "Add Podfile.lock to lock CocoaPods dependencies"
    
  2. 다음 중 하나로 프로젝트를 빌드할 수 있습니다.

    • xcodebuild 명령줄 도구:

      # Install CocoaPods dependencies
      pod install
      
      # Build the project
      xcodebuild -workspace YourWorkspace.xcworkspace -scheme YourScheme build
      
    • Xcode IDE:

      1. Xcode에서 .xcworkspace 파일을 엽니다.
      2. 대상 스킴을 선택합니다.
      3. Product > Build를 선택합니다. ⌘+B를 눌러도 됩니다.
    • iOS 및 Android 앱의 빌드와 릴리스를 자동화하는 도구인 fastlane:

      1. fastlane을 설치합니다.

        sudo gem install fastlane
        
      2. 프로젝트에서 fastlane을 구성합니다.

        fastlane init
        
      3. fastfile에 lane을 추가합니다.

        lane :build do
          cocoapods
          gym(scheme: "YourScheme")
        end
        
      4. 빌드를 실행합니다.

        fastlane build
        
    • 프로젝트가 CocoaPods와 Carthage를 모두 사용하면 Carthage로 의존성을 빌드할 수 있습니다.

      1. CocoaPods 의존성을 포함하는 Cartfile을 생성합니다.

      2. 다음을 실행합니다.

        carthage update --platform iOS
        
  3. 선호하는 방법에 따라 프로젝트를 빌드하도록 CI/CD를 구성합니다.

    예를 들어 xcodebuild를 사용하면 다음과 같습니다.

    cocoapods-build:
      stage: build
      script:
        - pod install
        - xcodebuild -workspace YourWorkspace.xcworkspace -scheme YourScheme build
    
  4. 선택 사항. 프라이빗 CocoaPods 리포지터리를 사용한다면 해당 리포지터리에 접근하도록 프로젝트를 구성해야 할 수 있습니다.

    1. 프라이빗 spec 리포지터리를 추가합니다.

      pod repo add REPO_NAME SOURCE_URL
      
    2. Podfile에 소스를 지정합니다.

      source 'https://github.com/CocoaPods/Specs.git'
      source 'SOURCE_URL'
      
  5. 선택 사항. 프라이빗 CocoaPods 리포지터리가 SSL을 사용한다면 SSL 인증서가 올바르게 구성되어 있는지 확인합니다.

    • 자체 서명 인증서를 사용한다면 시스템의 신뢰할 수 있는 인증서에 추가합니다. .netrc 파일에 SSL 구성을 지정할 수도 있습니다.

      machine your.private.repo.url
        login your_username
        password your_password
      
  6. Podfile을 업데이트한 후 pod install을 실행해 의존성을 설치하고 워크스페이스를 업데이트합니다.

모든 의존성이 올바르게 설치되고 워크스페이스가 업데이트되도록 Podfile을 업데이트한 후에는 항상 pod install을 실행합니다.

취약점 데이터베이스에 기여#

취약점을 찾으려면 GitLab advisory database에서 검색할 수 있습니다. 새 취약점을 제출할 수도 있습니다.