규칙 집합 사용자 정의
- 활성화됨: GitLab 16.2에서 모호한 패스스루 참조를 지정하는 지원.
해당 리포지토리에서 스캔하는 동안 규칙 집합 구성 파일을 정의함으로써 SAST 분석기의 동작을 사용자 정의할 수 있습니다. 사용자 정의의 두 가지 유형이 있습니다:
-
미리 정의된 규칙의 동작 수정. 여기에는 다음이 포함됩니다:
- 미리 정의된 규칙 비활성화. 모든 분석기에서 사용 가능.
- 미리 정의된 규칙 재정의. 모든 분석기에서 사용 가능.
- 패스스루를 사용하여 사용자 정의 구성 만들기로 미리 정의된 규칙을 교체. Semgrep 기반 분석기에서만 사용 가능.
고급 SAST는 미리 정의된 규칙의 동작을 수정하는 것만 지원하며, 미리 정의된 규칙을 교체하는 것은 지원하지 않습니다.
미리 정의된 규칙 비활성화
모든 SAST 분석기에 대해 미리 정의된 규칙을 비활성화할 수 있습니다.
규칙을 비활성화하면:
- 대부분의 분석기는 여전히 취약성을 스캔합니다. 결과는 스캔이 완료된 후 처리 단계에서 제거되며,
gl-sast-report.json
아티팩트에 나타나지 않습니다. - 비활성화된 규칙에 대한 발견 사항은 더 이상 파이프라인 보안 탭에 나타나지 않습니다.
- 기본 브랜치에서 비활성화된 규칙에 대한 기존 발견 사항은 취약점 보고서에서
더 이상 발견되지 않음
으로 표시됩니다.
Semgrep 기반 분석기는 비활성화된 규칙을 다르게 처리합니다:
- 성능 향상을 위해, Semgrep 기반 분석기는 비활성화된 규칙을 전혀 스캔하지 않습니다.
- Semgrep 기반 분석기에서 규칙을 비활성화하면, 해당 규칙에 대한 기존 취약점 발견 사항은
sast-ruleset.toml
파일을 기본 브랜치에 병합한 후 자동으로 해결됩니다.
이 동작을 구성하는 방법에 대한 정보는 스키마 및 예제 섹션을 참조하십시오.
미리 정의된 규칙 재정의
특정 미리 정의된 규칙의 속성은 모든 SAST 분석기에 대해 재정의할 수 있습니다. 이는 SAST를 기존 워크플로우나 도구에 맞추는 데 유용할 수 있습니다. 예를 들어, 조직 정책에 따라 취약점의 심각도를 재정의하거나 취약점 보고서에 표시될 다른 메시지를 선택할 수 있습니다.
이 동작을 구성하는 방법에 대한 정보는 스키마 및 예제 섹션을 참조하십시오.
사용자 정의 구성 만들기
Semgrep 기반 분석기에 대해 GitLab 유지 관리 규칙 집합을 자신의 규칙으로 교체할 수 있습니다.
패스스루를 통해 사용자 정의를 제공하며, 이는 런타임에 패스스루 체인으로 구성되고 평가되어 완전한 구성을 생성합니다. 그런 다음 기본 스캐너가 이 새로운 구성에 대해 실행됩니다.
파일을 리포지토리에 커밋하거나 규칙 집합 구성 파일 내에 인라인으로 사용하는 등의 다양한 방법으로 구성을 제공할 수 있는 여러 유형의 패스스루가 있습니다. 또한 체인 내에서 후속 패스스루가 어떻게 처리될지 선택할 수 있으며, 이전 구성을 덮어쓰거나 추가할 수 있습니다.
이 동작을 구성하는 방법에 대한 정보는 스키마 및 예제 섹션을 참조하십시오.
구성 파일 작성
규칙 세트 구성 파일을 작성하려면:
- 프로젝트의 루트에
.gitlab
디렉터리를 생성합니다. 디렉터리가 아직 존재하지 않는 경우에만 생성합니다. -
.gitlab
디렉터리에sast-ruleset.toml
이라는 파일을 생성합니다.
원격 구성 파일 지정
- 16.1에서 도입됨.
현재 리포지토리 외부에 저장된 규칙 세트 구성 파일을 사용하기 위해 CI/CD 변수를 설정할 수 있습니다.
이렇게 하면 여러 프로젝트에서 동일한 규칙을 적용할 수 있습니다.
SAST_RULESET_GIT_REFERENCE
변수는 프로젝트 URI, 선택적 인증 및 선택적 Git SHA를 지정하기 위한 Git URL과 유사한 형식을 사용합니다. 변수는 다음 형식을 사용합니다:
[<AUTH_USER>[:<AUTH_PASSWORD>]@]<PROJECT_PATH>[@<GIT_SHA>]
참고:
프로젝트에 .gitlab/sast-ruleset.toml
파일이 커밋된 경우, 해당 로컬 구성이 우선하며 SAST_RULESET_GIT_REFERENCE
에서 파일을 사용하지 않습니다.
다음 예시는 SAST를 활성화하고 공유 규칙 세트 사용자 지정 파일을 사용합니다. 이 예에서 파일은 example-ruleset-project
의 기본 브랜치에 .gitlab/sast-ruleset.toml
경로로 커밋됩니다.
include:
- template: Jobs/SAST.gitlab-ci.yml
variables:
SAST_RULESET_GIT_REFERENCE: "gitlab.com/example-group/example-ruleset-project"
고급 사용법을 위해 비공식 원격 구성 예제를 참조하세요.
원격 구성 파일 문제 해결
원격 구성 파일이 사용자 지정을 올바르게 적용하지 않는 경우 원인은 다음과 같을 수 있습니다:
- 레포지토리에 로컬
.gitlab/sast-ruleset.toml
파일이 있습니다.- 기본적으로 로컬 파일이 존재하는 경우, 원격 구성이 변수로 설정되어 있어도 로컬 파일이 사용됩니다.
-
SECURE_ENABLE_LOCAL_CONFIGURATION CI/CD 변수를
false
로 설정하여 로컬 구성 파일을 무시할 수 있습니다.
- 인증에 문제가 있습니다.
- 이것이 문제의 원인인지 확인하려면 인증이 필요하지 않은 리포지토리 위치에서 구성 파일을 참조해 보세요.
스키마
최상위 섹션
최상위 섹션은 하나 이상의 _구성 섹션_을 포함하며, 이는 TOML 테이블로 정의됩니다.
설정 | 설명 |
---|---|
[$analyzer] |
분석기에 대한 구성 섹션을 선언합니다. 이름은 SAST 분석기 목록에 정의된 스네이크 케이스 이름을 따릅니다. |
구성 예:
[semgrep]
...
기존 규칙을 수정하는 구성 섹션을 만들고 사용자 지정 규칙 세트를 구축하는 것은 피하세요.
[$analyzer]
구성 섹션
[$analyzer]
섹션을 사용하면 분석기의 동작을 사용자 지정할 수 있습니다. 유효한 속성은 만드는 구성 종류에 따라 다릅니다.
설정 | 적용 대상 | 설명 |
---|---|---|
[[$analyzer.ruleset]] |
미리 정의된 규칙 | 기존 규칙에 대한 수정을 정의합니다. |
interpolate |
모든 |
true 로 설정하면 환경 변수를 평가하기 위해 구성 내에서 $VAR 를 사용할 수 있습니다. 이 기능은 비밀이나 토큰이 유출되지 않도록 주의해서 사용하세요. (기본값: false ) |
description |
패스스루 | 사용자 지정 규칙 세트의 설명입니다. |
targetdir |
패스스루 | 최종 구성이 저장되어야 하는 디렉터리입니다. 비어 있으면 랜덤 이름의 디렉터리가 생성됩니다. 디렉터리는 최대 100MB의 파일을 포함할 수 있습니다. |
validate |
패스스루 |
true 로 설정하면 각 패스스루의 내용이 검증됩니다. 검증은 yaml , xml , json 및 toml 내용에 대해 작동합니다. 적절한 검증기는 [[$analyzer.passthrough]] 섹션의 target 매개변수에 사용된 확장자를 기반으로 식별됩니다. (기본값: false ) |
timeout |
패스스루 | 타임아웃되기 전 패스스루 체인을 평가하는 데 소요되는 최대 시간입니다. 타임아웃은 300초를 초과할 수 없습니다. (기본값: 60) |
interpolate
경고:
비밀 정보 유출 위험을 줄이기 위해 이 기능을 사용할 때 주의하세요.
아래 예시는 $GITURL
환경 변수를 사용하여 비공개 리포지토리에 접근하는 구성 예입니다. 이 변수에는 사용자 이름과 토큰이 포함되어 있으므로(예: https://user:token@url
), 구성 파일에 명시적으로 저장되지 않습니다.
[semgrep]
description = "내 비공식 Semgrep 규칙 집합"
interpolate = true
[[semgrep.passthrough]]
type = "git"
value = "$GITURL"
ref = "main"
[[$analyzer.ruleset]]
섹션
[[$analyzer.ruleset]]
섹션은 단일 미리 정의된 규칙을 타겟으로 하여 수정합니다. 애널라이저당 이 섹션을 한 개 이상 정의할 수 있습니다.
설정 | 설명 |
---|---|
disable |
규칙을 비활성화할지 여부입니다. (기본값: false ) |
[$analyzer.ruleset.identifier] |
수정할 미리 정의된 규칙을 선택합니다. |
[$analyzer.ruleset.override] |
규칙에 대한 오버라이드를 정의합니다. |
구성 예시:
[semgrep]
[[semgrep.ruleset]]
disable = true
...
[$analyzer.ruleset.identifier]
섹션
[$analyzer.ruleset.identifier]
섹션은 수정할 미리 정의된 규칙의 식별자를 정의합니다.
설정 | 설명 |
---|---|
type |
미리 정의된 규칙에서 사용되는 식별자의 유형입니다. |
value |
미리 정의된 규칙에서 사용되는 식별자의 값입니다. |
올바른 type
및 value
의 값을 보려면 애널라이저에 의해 생성된 gl-sast-report.json
을 확인하면 됩니다. 이 파일은 애널라이저의 CI 작업에서 작업 아티팩트로 다운로드할 수 있습니다.
예를 들어, 아래 코드 조각은 세 개의 식별자를 가진 semgrep
규칙의 발견을 보여줍니다. JSON 객체의 type
및 value
키는 이 섹션에서 제공해야 하는 값에 해당합니다.
...
"vulnerabilities": [
{
"id": "7331a4b7093875f6eb9f6eb1755b30cc792e9fb3a08c9ce673fb0d2207d7c9c9",
"category": "sast",
"message": "엔터티 인증 없이 키 교환",
"description": "ssh.InsecureIgnoreHostKey 사용 감사\n",
...
"identifiers": [
{
"type": "semgrep_id",
"name": "gosec.G106-1",
"value": "gosec.G106-1"
},
{
"type": "cwe",
"name": "CWE-322",
"value": "322",
"url": "https://cwe.mitre.org/data/definitions/322.html"
},
{
"type": "gosec_rule_id",
"name": "Gosec 규칙 ID G106",
"value": "G106"
}
]
}
...
]
...
구성 예시:
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.identifier]
type = "semgrep_id"
value = "gosec.G106-1"
...
[$analyzer.ruleset.override]
섹션
[$analyzer.ruleset.override]
섹션을 사용하면 미리 정의된 규칙의 속성을 덮어쓸 수 있습니다.
설정 | 설명 |
---|---|
description |
문제에 대한 자세한 설명입니다. |
message |
(더 이상 사용되지 않음) 문제에 대한 설명입니다. |
name |
규칙의 이름입니다. |
severity |
규칙의 심각도입니다. 유효한 옵션은 Critical , High , Medium , Low , Unknown , Info 입니다. |
참고:
message
는 분석기에 의해 채워지지만 name
과 description
을 대신하여 더 이상 사용되지 않음으로 표시되었습니다.
구성 예시:
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.override]
severity = "Critical"
name = "Command injection"
...
[[$analyzer.passthrough]]
섹션
참고: Passthrough 구성은 Semgrep 기반 분석기에서만 사용할 수 있습니다.
[[$analyzer.passthrough]]
섹션을 사용하면 분석기를 위한 사용자 지정 구성을 만들 수 있습니다.
분석기당 최대 20개의 이러한 섹션을 정의할 수 있습니다. Passthrough는 _passthrough 체인_으로 조합되어 분석기의 미리 정의된 규칙을 대체하는 완전한 구성을 평가합니다.
Passthrough는 순서대로 평가됩니다. 체인에서 나중에 나열된 passthrough는 더 높은 우선 순위를 가지며 이전 passthrough에서 발생한 데이터를 덮어쓰거나 추가할 수 있습니다(모드에 따라 다름). 이는 기존 구성을 사용하거나 수정해야 하는 사례에 유용합니다.
단일 passthrough에 의해 생성된 구성의 크기는 10 MB로 제한됩니다.
설정 | 적용 대상 | 설명 |
---|---|---|
type |
모두 |
file , raw , git , 또는 url 중 하나입니다. |
target |
모두 | passthrough 평가에 의해 작성된 데이터가 포함될 대상 파일입니다. 비어 있으면 임의의 파일명이 사용됩니다. |
mode |
모두 |
overwrite 인 경우 target 파일이 덮어쓰여집니다. append 인 경우 새 콘텐츠가 target 파일에 추가됩니다. git 유형은 overwrite 만 지원합니다. (기본값: overwrite ) |
ref |
type = "git" |
가져올 브랜치, 태그 또는 SHA의 이름을 포함합니다. |
subdir |
type = "git" |
Git 저장소의 하위 디렉터리를 구성 소스로 선택하는 데 사용됩니다. |
value |
모두 |
file , url , 및 git 유형의 경우 파일이나 Git 저장소의 위치를 정의합니다. raw 유형의 경우 인라인 구성을 포함합니다. |
validator |
모두 | passthrough 평가 후 대상 파일에 대해 명시적으로 유효성 검사기(xml , yaml , json , toml )를 호출하는 데 사용됩니다. |
Passthrough 유형
유형 | 설명 |
---|---|
file |
Git 저장소에 존재하는 파일을 사용합니다. |
raw |
구성을 인라인으로 제공합니다. |
git |
원격 Git 저장소에서 구성을 가져옵니다. |
url |
HTTP를 사용하여 구성을 가져옵니다. |
경고:
YAML 스니펫과 함께 raw
passthrough를 사용할 때는 sast-ruleset.toml
파일의 모든 들여쓰기를 공백으로 형식화하는 것이 좋습니다. YAML 사양은 탭보다 공백을 요구하며, 분석기는 들여쓰기가 적절하게 표현되지 않으면 사용자 지정 규칙 집합을 구문 분석하지 못합니다.
예제
SAST 분석기의 미리 정의된 규칙 비활성화
다음 사용자 정의 규칙 세트 구성으로 인해 다음 규칙이 보고서에서 생략됩니다:
-
semgrep
규칙 중semgrep_id
가gosec.G106-1
또는cwe
가322
인 규칙. -
sobelow
규칙 중sobelow_rule_id
가sql_injection
인 규칙. -
flawfinder
규칙 중flawfinder_func_name
가memcpy
인 규칙.
[semgrep]
[[semgrep.ruleset]]
disable = true
[semgrep.ruleset.identifier]
type = "semgrep_id"
value = "gosec.G106-1"
[[semgrep.ruleset]]
disable = true
[semgrep.ruleset.identifier]
type = "cwe"
value = "322"
[sobelow]
[[sobelow.ruleset]]
disable = true
[sobelow.ruleset.identifier]
type = "sobelow_rule_id"
value = "sql_injection"
[flawfinder]
[[flawfinder.ruleset]]
disable = true
[flawfinder.ruleset.identifier]
type = "flawfinder_func_name"
value = "memcpy"
SAST 분석기의 미리 정의된 규칙 재정의
다음 사용자 정의 규칙 세트 구성으로 인해 semgrep
에서 발견된 CWE
유형과 322
값을 가진 취약점의 심각도가 Critical
로 재정의됩니다.
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.identifier]
type = "cwe"
value = "322"
[semgrep.ruleset.override]
severity = "Critical"
semgrep
을 위한 파일 패스스루를 사용한 사용자 정의 구성 빌드
다음 사용자 정의 규칙 세트 구성으로 인해 semgrep
분석기의 미리 정의된 규칙 세트가 리포지토리에 있는 my-semgrep-rules.yaml
라는 파일에 포함된 사용자 정의 규칙 세트로 교체됩니다.
# my-semgrep-rules.yml
---
rules:
- id: my-custom-rule
pattern: print("Hello World")
message: |
Unauthorized use of Hello World.
severity: ERROR
languages:
- python
[semgrep]
description = "My custom ruleset for Semgrep"
[[semgrep.passthrough]]
type = "file"
value = "my-semgrep-rules.yml"
semgrep
을 위한 패스스루 체인을 사용한 사용자 정의 구성 빌드
다음 사용자 정의 규칙 세트 구성으로 인해 semgrep
분석기의 미리 정의된 규칙 세트가 네 개의 패스스루를 평가하여 생성된 사용자 정의 규칙 세트로 교체됩니다. 각 패스스루는 컨테이너 내의 /sgrules
디렉토리에 작성되는 파일을 생성합니다. Git 원격이 응답하지 않을 경우를 대비해 timeout
이 60초로 설정됩니다.
이 예에서 다양한 패스스루 유형이 시연됩니다:
- 두 개의
git
패스스루, 첫 번째는myrules
Git 리포지토리에서develop
브랜치를 가져오고, 두 번째는sast-rules
리포지토리에서 리비전97f7686
을 가져오고go
하위 디렉토리의 파일만 고려합니다.-
sast-rules
항목은 구성에서 나중에 나타나기 때문에 우선 순위가 더 높습니다. - 두 개의 체크아웃 간에 파일 이름 충돌이 발생할 경우,
sast-rules
리포지토리의 파일이myrules
리포지토리의 파일을 덮어씁니다.
-
-
raw
패스스루는/sgrules/insecure.yml
에 자신의value
를 씁니다. -
url
패스스루는 URL에 호스팅된 구성을 가져와/sgrules/gosec.yml
에 씁니다.
그 후, Semgrep은 /sgrules
아래에 있는 최종 구성으로 호출됩니다.
[semgrep]
description = "My custom ruleset for Semgrep"
targetdir = "/sgrules"
timeout = 60
[[semgrep.passthrough]]
type = "git"
value = "https://gitlab.com/user/myrules.git"
ref = "develop"
[[semgrep.passthrough]]
type = "git"
value = "https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/playground/sast-rules.git"
ref = "97f7686db058e2141c0806a477c1e04835c4f395"
subdir = "go"
[[semgrep.passthrough]]
type = "raw"
target = "insecure.yml"
value = """
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function insecure detected
metadata:
cwe: "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor"
severity: "ERROR"
languages:
- "go"
"""
[[semgrep.passthrough]]
type = "url"
value = "https://semgrep.dev/c/p/gosec"
target = "gosec.yml"
체인의 패스스루 모드 구성
체인 내에서 발생하는 파일 이름 충돌을 처리하는 방법을 선택할 수 있습니다. 기본 동작은 동일한 이름의 기존 파일을 덮어쓰는 것이지만, 대신 mode = append
를 선택하여 후속 파일의 내용을 이전 파일에 추가할 수 있습니다.
append
모드는 file
, url
, raw
패스스루 타입에 대해서만 사용할 수 있습니다.
다음 사용자 정의 규칙 집합 구성에서는 두 개의 raw
패스스루를 사용하여 /sgrules/my-rules.yml
파일을 반복적으로 조합하며, 이 파일은 Semgrep에 규칙 집합으로 제공됩니다. 각 패스스루는 규칙 집합에 단일 규칙을 추가합니다. 첫 번째 패스스루는 Semgrep 규칙 문법에 따라 최상위 rules
객체를 초기화하는 역할을 합니다.
[semgrep]
description = "My custom ruleset for Semgrep"
targetdir = "/sgrules"
validate = true
[[semgrep.passthrough]]
type = "raw"
target = "my-rules.yml"
value = """
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function 'insecure' detected
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
"""
[[semgrep.passthrough]]
type = "raw"
mode = "append"
target = "my-rules.yml"
value = """
- id: "secret"
patterns:
- pattern-either:
- pattern: '$MASK = "..."'
- metavariable-regex:
metavariable: "$MASK"
regex: "(password|pass|passwd|pwd|secret|token)"
message: |
Use of hard-coded password
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
"""
# /sgrules/my-rules.yml
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function 'insecure' detected
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
- id: "secret"
patterns:
- pattern-either:
- pattern: '$MASK = "..."'
- metavariable-regex:
metavariable: "$MASK"
regex: "(password|pass|passwd|pwd|secret|token)"
message: |
Use of hard-coded password
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
개인 원격 구성 지정
다음 예제는 SAST를 활성화하고 공유 규칙 집합 사용자 지정 파일을 사용합니다. 파일은 다음과 같습니다:
- 인증이 필요한 개인 프로젝트에서 다운로드되며, 그룹 액세스 토큰을 사용하여 CI 변수에 안전하게 저장됩니다.
- 기본 브랜치 대신 특정 Git 커밋 SHA에서 체크아웃됩니다.
그룹 액세스 토큰을 참조하여 그룹 토큰과 연관된 사용자 이름을 찾는 방법을 알아보세요.
include:
- template: Jobs/SAST.gitlab-ci.yml
variables:
SAST_RULESET_GIT_REFERENCE: "group_2504721_bot_7c9311ffb83f2850e794d478ccee36f5:$PERSONAL_ACCESS_TOKEN@gitlab.com/example-group/example-ruleset-project@c8ea7e3ff126987fb4819cc35f2310755511c2ab"
데모 프로젝트
이 데모 프로젝트는 이러한 구성 옵션 중 일부를 설명합니다.
이러한 프로젝트 중 많은 부분은 원격 규칙 세트를 사용하여 규칙을 오버라이드하거나 비활성화하는 방법을 보여주며, 어떤 분석기를 위한 것인지에 따라 그룹화되어 있습니다.
원격 규칙 세트를 설정하는 과정을 설명하는 비디오 데모도 있습니다: