SARIF 보고서
GitLab v19.4Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
요약
서드파티 SARIF 보고서를 사용하면 SARIF 2.1.0 스캐너의 결과를 GitLab 취약점 관리에 추가할 수 있습니다. 보고서를 추가하면 GitLab 기본 스캐너의 결과와 함께 다음 페이지에 해당 결과가 표시됩니다.
히스토리
서드파티 SARIF 보고서를 사용하면 SARIF 2.1.0 스캐너의 결과를 GitLab 취약점 관리에 추가할 수 있습니다. CI/CD job 이 SARIF를 생성하는 스캐너를 실행하고 SARIF 아티팩트를 추가합니다. GitLab은 이 아티팩트를 파싱하고 검증한 뒤 보안 결과로 추가합니다.
보고서를 추가하면 GitLab 기본 스캐너의 결과와 함께 다음 페이지에 해당 결과가 표시됩니다.
- 파이프라인 Security 탭
- 프로젝트 취약점 보고서
- 보안 대시보드
- 머지 리퀘스트 보안 위젯
- 보안 정책
서드파티 SARIF 보고서는 GitLab 이 제공하는 기본 스캐너를 보완합니다. GitLab 이 자체적으로 제공하지 않는 서드파티 스캐너를 연동하거나, 이미 사용 중인 도구의 결과를 한곳에 모을 때 사용합니다.
SARIF 보고서 추가#
GitLab에 SARIF 결과를 추가하려면 다음 절차를 수행합니다.
사전 요구 사항:
- 프로젝트에 대한 Maintainer 또는 Owner 권한.
- SARIF 2.1.0 파일을 생성하는 CI/CD job.
-
.gitlab-ci.yml파일에서 스캐너를 실행하고 SARIF 출력을artifacts:reports:sarif아티팩트로 저장하는 job을 정의합니다. 예시:sarif_scan: image: <scanner-image> script: - <scanner-command> --output sarif.json artifacts: reports: sarif: sarif.json -
변경 사항을 커밋하고 푸시합니다. job 이 완료되면 GitLab 이 SARIF 파일을 파싱합니다.
-
파이프라인 Security 탭에서 추가된 결과를 확인합니다.
CI/CD 아티팩트 참조는
artifacts:reports:sarif를 참고합니다.
할당된 보고서 유형#
GitLab은 각 SARIF 결과의 위치와 식별자를 기준으로 취약점 보고서 유형을 할당합니다. 이 유형은 결과가 취약점 보고서의 어디에 표시되는지, 그리고 보안 정책과 어떻게 상호작용하는지를 결정합니다.
GitLab은 다음 규칙을 순서대로 평가하고, 결과와 처음으로 일치하는 유형을 할당합니다.
| 규칙 | 할당된 보고서 유형 |
|---|---|
| 식별자 중 하나가 CVE 인 경우. | 의존성 스캐닝 |
| 식별자 중 하나가 시크릿 관련 CWE 인 경우. 1 | 시크릿 탐지 |
| 기본값(어떤 규칙도 일치하지 않는 경우) | SAST |
각주:
-
다음 CWE가 시크릿 관련 항목입니다.
GitLab은 결과와 그 규칙에서 다음 세 가지 소스를 이 순서로 읽어 식별자를 가져옵니다.
result.ruleId— 항목이CVE-YYYY-N또는CWE-N형식과 일치하는 경우.rule.properties.tags[]— 항목이cwe:N,cwe-N,cve:YYYY-N또는cve-YYYY-N형식과 일치하는 경우.rule.relationships[]— 관계의target.toolComponent.name이CWE인 경우.
CVE 또는 지원되는 CWE 식별자가 없는 결과는 SAST로 할당됩니다. GitLab 이 할당하는 유형을 변경하려면 일치하는 CVE 또는 CWE 식별자를 생성하도록 스캐너를 구성합니다.
SARIF 필드 매핑#
GitLab은 다음 규칙에 따라 SARIF 필드를 GitLab과 호환되는 필드에 할당합니다.
| GitLab 필드 | SARIF 소스 | 필수 여부 | 비고 |
|---|---|---|---|
| 심각도 | 심각도 결정 참고 | ❌ | 심각도 필드가 설정되지 않은 경우 기본값은 medium 입니다. |
| 기본 식별자 | result.ruleId가 run.tool.driver.rules[].id의 해당 값과 매칭됩니다 |
✅ | ruleId가 없는 결과는 추가되지 않습니다. |
| 보조 식별자 | rule.properties.tags[] 및 rule.relationships[] |
❌ | 보고서 유형 할당에 사용됩니다. |
| 위치 | result.locations[0].physicalLocation |
✅ | 물리적 위치가 없는 결과는 추가되지 않습니다. 같은 파일에서 ruleId가 같고 region 이 없는 결과는 하나의 결과로 합쳐집니다. 중복 제거 및 결과 식별을 참고합니다. |
| 스캐너 이름 | run.tool.driver.name |
✅ | 유효한 SARIF에 필수입니다 |
| 스캐너 공급업체 | run.tool.driver.organization, 그다음 run.tool.driver.informationUri |
❌ | 비어 있지 않은 첫 번째 값이 사용됩니다 |
| 스캐너 버전 | run.tool.driver.version, 그다음 run.tool.driver.semanticVersion |
❌ | 비어 있지 않은 첫 번째 값이 사용됩니다 |
| 억제 | result.suppressions[] |
❌ | 모든 억제가 underReview 또는 rejected 인 경우를 제외하고, 억제된 결과는 건너뜁니다. |
심각도 결정#
GitLab은 다음 필드를 우선순위 순서대로 확인해 SARIF 결과의 심각도를 결정합니다. 값이 있는 첫 번째 필드가 사용됩니다.
result.rank.0.0부터100.0까지의 실수입니다.rule.properties.security-severity.0.0부터10.0까지의 실수입니다. 이 값은 구간을 나누기 전에 10 이 곱해집니다.result.properties.security-severity.0.0부터10.0까지의 실수입니다. 이 값은 구간을 나누기 전에 10 이 곱해집니다.result.level.rule.defaultConfiguration.level.- 다른 항목이 일치하지 않는 경우 기본값
medium.
result.rank 또는 security-severity의 숫자 점수는 다음 범위에 따라 심각도로
할당됩니다.
| 점수 (0-100) | 심각도 |
|---|---|
0.0-9.9 |
Info |
10.0-39.9 |
Low |
40.0-69.9 |
Medium |
70.0-89.9 |
High |
90.0-100 |
Critical |
SARIF level 값은 다음과 같이 매핑됩니다.
level |
심각도 |
|---|---|
error |
High |
warning |
Medium |
note |
Low |
none |
Info |
GitLab은 level: error를 critical 이 아니라 high로 할당합니다. critical 결과로 보고하려면
result.rank를 90 이상으로 설정하거나 security-severity를 9.0 이상으로 설정합니다.
수집 동작#
SARIF 파일 형식은 올바르지만 일부 결과를 추가할 수 없는 경우, GitLab은 처리하지 못한 결과의 비율을 기준으로 스캔 전체를 어떻게 처리할지 결정합니다.
| 드롭 비율 | 동작 | 보고 방식 |
|---|---|---|
| 0% | 모든 결과가 수집됩니다. | 메시지 없음. |
| 1% ~ 50% | 유효한 결과가 수집됩니다. | 드롭 수와 함께 경고. |
| 50% 초과 | 스캔 전체가 실패합니다. 보고서의 어떤 결과도 수집되지 않습니다. | 드롭 수와 함께 오류. |
GitLab 이 결과를 처리할 수 없는 경우는 다음과 같습니다.
ruleId가 없습니다.physicalLocation이 없습니다.- 결과 식별자를 생성하는 데 사용되는 필수 구성 요소 중 하나가 nil 입니다.
- 문자열 필드가 문자 수 제한을 초과합니다.
드롭 비율은 파일의 각 run 이 아니라 SARIF 아티팩트 전체를 기준으로 계산됩니다. 모든 run에 걸친
처리 불가 결과의 비율이 임계값을 초과하면, 해당 아티팩트에서 생성된 모든 보고서에
수집 피드백이 적용됩니다.
스키마 검증 오류와 지원되지 않는 SARIF 버전은 드롭 비율과 관계없이 보고서 전체가 거부되는 원인이 됩니다.
다중 도구 보고서#
하나의 SARIF 파일에는 여러 도구 실행이 포함될 수 있고, 각각은 자체 runs[] 항목을 가집니다. GitLab은
각 run에 대해 추론된 보고서 유형별로 결과를 그룹화하고, 그룹마다 별도의 스캔 레코드를
생성합니다. 추론된 유형이 둘 이상인 결과를 포함한 run은
둘 이상의 스캔 레코드를 생성합니다. 각 스캔은 해당 run의 tool.driver.name을
스캐너로 사용합니다.
여러 스캐너의 출력을 하나의 아티팩트로 합칠 때 다중 run 보고서를 사용합니다. 예를 들어 하나의 job 이 스캐너 두 개를 실행하고, run 두 개가 포함된 단일 SARIF 파일을 생성할 수 있습니다.
파일당 run 제한은 제한을 참고합니다.
제한#
| 제한 | 기본값 | 구성 가능 여부 |
|---|---|---|
| 최대 SARIF 아티팩트 크기 | 10 MB (ci_max_artifact_size_sarif) |
✅ |
| SARIF 파일당 최대 run 수 | 20 | ❌ |
| run 당 최대 결과 수 | 5,000 | ❌ |
| run 당 최대 규칙 수 | 25,000 | ❌ |
| 규칙당 최대 태그 수 | 10 | ❌ |
최대 rule.name 길이 |
255자 | ❌ |
최대 shortDescription.text 길이 |
1,024자 | ❌ |
최대 fullDescription.text 길이 |
1,024자, 결과 제목으로 사용하면 255자로 잘림 | ❌ |
최대 message.text 길이 |
1,024자, 결과 제목으로 사용하면 255자로 잘림 | ❌ |
최대 helpUri 길이 |
2,048자 | ❌ |
| 지원되는 SARIF 버전 | 2.1.0만 지원 | ❌ |
run 당 개수가 제한을 초과하면 GitLab은 처음 N 개 항목을 처리하고 경고를 기록합니다. 결과에 문자 수 제한을 초과하는 문자열 필드가 있으면 해당 결과 전체를 건너뛰고 드롭 비율에 포함합니다.
GitLab Self-Managed 인스턴스에서는 관리자가 인스턴스 제한을 통해 구성 가능한 제한을 변경할 수 있습니다.
중복 제거 및 결과 식별#
GitLab은 SARIF 보고서를 수집할 때 각 결과에 세 가지 구성 요소로 만들어진 고유 식별 정보를
부여합니다. 세 가지는 보고서 유형, 결과의 ruleId에서 파생된 기본 식별자 지문,
그리고 위치 지문입니다.
SARIF 결과에서 위치 지문은 file:startLine:endLine 형식을 가집니다.
SARIF physicalLocation은 region 없이 artifactLocation.uri로 파일을 지정할 수 있습니다.
이 경우에도 GitLab은 결과를 수집하며, 시작 줄과 끝 줄 없이 파일 전체를
위치로 지정합니다.
결과 둘 이상이 같은 파일과 같은 ruleId를 공유하고 그중 어느 것도 region을 가지지 않으면,
세 가지 식별 구성 요소가 모두 일치합니다. 이 결과들은 같은 규칙으로 해석되므로 보고서 유형과
기본 식별자 지문을 공유하고, 위치 지문은 파일 경로만으로 대체됩니다. GitLab은 각 결과에 대해
같은 식별 정보를 계산하므로, 첫 번째 결과만 남기고 나머지는
버립니다.
이 충돌은 GitLab 이 수집을 건너뛸 때가 아니라 식별 정보를 할당할 때 발생하므로, 이렇게 버려진 결과는 수집 드롭 비율에 포함되지 않고 GitLab도 경고를 표시하지 않습니다.
이 충돌을 피하려면 같은 파일의 각 결과가 고유한 위치 지문을 가지도록 최소한 startLine 이 포함된
region을 생성합니다.
알려진 문제#
- SAST, 의존성 스캐닝, 시크릿 탐지로 할당된 SARIF 결과는 동등한 GitLab 기본 스캐너의 결과와 중복 제거되지 않습니다. 자세한 내용은 이슈 592410을 참고합니다.
- SARIF 억제로 결과를 제외할 수는 있지만, GitLab은 억제를 근거로 취약점 무시 처리를 생성하지 않습니다. 결과를 무시 처리하려면 취약점 보고서를 사용합니다.
관련 주제#
문제 해결#
SARIF 보고서를 추가할 때 다음과 같은 문제가 발생할 수 있습니다.
경고: ... result(s) were skipped during ingestion#
파이프라인의 Security 탭에서 다음과 유사한 메시지를 포함한 Warning parsing security reports 알림이 표시될 수 있습니다.
[Ingestion] 8 of 69 result(s) were skipped during ingestion. Causes: text field exceeded length limit (8). Check application logs for per-result details.
이 문제는 SARIF 보고서의 결과가 제한에 설명된 요구 사항을 충족하지 않을 때 발생합니다. GitLab은 해당 결과를 건너뛰고 나머지 결과를 수집합니다.
보고서 결과의 절반을 넘게 건너뛰면 메시지가 경고가 아니라 오류로 표시되고
could not be ingested and the scan was aborted로 끝납니다. 이 경우 GitLab은 해당 보고서의
어떤 결과도 저장하지 않습니다.
이 문제를 해결하려면 모든 결과가 문서화된 제한을 충족하도록 스캐너 구성이나 SARIF 보고서를 수정한 다음, 파이프라인을 새로 실행합니다.
원인을 조사하려면 다음을 수행합니다.
- GitLab.com에서는 GitLab 팀원이 Kibana에서
다음 필터로
pubsub-sidekiq-inf-gprd*인덱스를 검색할 수 있습니다.json.meta.feature_category: vulnerability_managementjson.meta.pipeline_id: <pipeline-id>json.message: Result skipped*또는json.message: SARIF finding skipped*
- GitLab Self-Managed에서는
application_json.log에서Result skipped:또는SARIF finding skipped:를 검색합니다.
로그는 어떤 필드나 속성이 결과를 건너뛰게 했는지는 알려주지만, 개별 결과를 특정하지는 않습니다.
GitLab Self-Managed에서는 Rails 콘솔 세션에서 저장된 메시지를 읽을 수도 있습니다.
scan = Security::Scan.find_by!(pipeline_id: <pipeline-id>, project_id: <project-id>)
scan.processing_warnings
scan.processing_errors
SARIF 보고서보다 적게 표시되는 결과#
SARIF 파일에 포함된 결과보다 적은 수의 결과가 수집 경고 없이 취약점 보고서에 표시될 수 있습니다.
이 문제는 결과 둘 이상이 같은 식별 정보로 해석되어 GitLab 이 첫 번째 결과만 남길 때 발생합니다. 자세한 내용은 중복 제거 및 결과 식별을 참고합니다.