사용자 정의 규칙 세트
- GitLab 13.5 에 도입되었습니다.
- GitLab 14.6에서는 passthrough chains의 지원이 확대되어
file
,git
, 및url
과 같은 추가 passthrough 유형이 포함되었습니다.- GitLab 14.8에서는 규칙을 재정의하는 지원이 활성화되었습니다.
- GitLab 16.2에서는 모호한 passthrough 참조를 지정하는 지원이 활성화되었습니다.
저희의 SAST 분석기의 동작을 규칙 세트 구성 파일을 정의하여 사용자 정의할 수 있습니다. 두 가지 종류의 사용자 정의가 있습니다:
-
미리 정의된 규칙의 동작 수정. 이에는 다음이 포함됩니다:
- 미리 정의된 규칙 비활성화. 모든 분석기에서 사용 가능.
- 미리 정의된 규칙 재정의. 모든 분석기에서 사용 가능.
- passthroughs를 사용하여 미리 정의된 규칙 교체. nodejs-scan 및 semgrep에만 사용 가능합니다.
미리 정의된 규칙 비활성화
어떤 SAST 분석기든지 미리 정의된 규칙을 비활성화할 수 있습니다.
규칙을 비활성화하면:
- 대부분의 분석기에서 여전히 취약점을 스캔합니다. 스캔이 완료된 후 결과는 처리 단계에서 제거되어
gl-sast-report.json
artifact에 표시되지 않습니다. - 비활성화된 규칙에 대한 결과는 더 이상 파이프라인 보안 탭에 나타나지 않습니다.
- 기본 브랜치에서 비활성화된 규칙에 대한 기존 결과는 취약성 보고서에서
No longer detected
로 표시됩니다.
Semgrep 기반 분석기는 비활성화된 규칙을 다르게 처리합니다:
- 성능을 개선하기 위해, Semgrep 기반 분석기는 비활성화된 규칙을 스캔하지 않습니다.
- Semgrep 기반 분석기에서 규칙을 비활성화하면 해당 규칙에 대한 기존 취약성 결과는
sast-ruleset.toml
파일을 기본 브랜치로 Merge한 후에 자동으로 해결됩니다.
이 동작에 대한 구성 방법에 대한 정보는 스키마 및 예제 섹션을 참조하세요.
미리 정의된 규칙 재정의
모든 SAST 분석기에서 미리 정의된 규칙의 특정 속성을 재정의할 수 있습니다. 이는 SAST를 기존의 워크플로우나 도구에 적응시킬 때 유용합니다. 예를 들어, 조직 정책에 따라 취약점의 심각도를 재정의하거나 취약성 보고서에 표시할 다른 메시지를 선택할 수 있습니다.
이 동작에 대한 구성 방법에 대한 정보는 스키마 및 예제 섹션을 참조하세요.
사용자 정의 구성 합성
일부 SAST 분석기의 미리 정의된 규칙을 완전히 교체할 수 있습니다:
- nodejs-scan - 기본 njsscan 구성 파일을 사용자 정의할 수 있습니다.
- semgrep - GitLab이 유지 관리하는 규칙 세트를 사용자 정의할 수 있습니다.
사용자 정의는 passthroughs를 통해 제공되며, 실행 시 passthrough 체인으로 구성되어 완전한 구성을 생성하고 평가됩니다. 그런 다음 기본 스캐너가이 새 구성에 대해 실행됩니다.
다양한 passthrough 유형이 있어 리포지터리에 커밋된 파일을 사용하거나 규칙 세트 구성 파일에 인라인으로 제공하는 등 다양한 방식으로 구성을 제공할 수 있습니다. 또한 체인의 이후 passthrough가 이전 구성을 덮어쓰거나 추가하는 방식을 선택할 수 있습니다.
이 동작에 대한 구성 방법에 대한 정보는 스키마 및 예제 섹션을 참조하세요.
구성 파일 생성
규칙 세트 구성 파일을 생성하려면:
- 프로젝트의 루트에
.gitlab
디렉터리를 생성합니다(존재하지 않는 경우). -
.gitlab
디렉터리에sast-ruleset.toml
이라는 파일을 생성합니다.
원격 구성 파일 지정
- 16.1에서 도입되었습니다.
현재 리포지터리 외부에 저장된 규칙 세트 구성 파일을 사용하려면 CI/CD 변수를 설정할 수 있습니다. 이를 통해 동일한 규칙을 여러 프로젝트에 적용할 수 있습니다.
SAST_RULESET_GIT_REFERENCE
변수는 프로젝트 URI, 선택적 인증, 그리고 선택적 Git SHA와 유사한 형식을 사용합니다.
이 변수는 다음 형식을 사용합니다:
[<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
파일이 있는 경우- 로컬 파일이 있다면 원격 구성이 변수로 설정되어 있더라도 로컬 파일이 사용됩니다.
- 이 논리의 변경은 issue 414732에서 고려됩니다.
- 인증에 문제가 있습니다.
- 문제의 원인이 여기에 있는지 확인하려면 인증이 필요하지 않은 리포지터리 위치에서 구성 파일을 참조해 보세요.
스키마
최상위 섹션
최상위 섹션에는 하나 이상의 _구성 섹션_이 포함되며, 이는 TOML 테이블로 정의됩니다.
설정 | 설명 |
---|---|
[$analyzer]
| 분석기에 대한 구성 섹션을 선언합니다. 이름은 SAST analyzers 디렉터리에서 정의된 스네이크 케이스 이름을 따릅니다. |
구성 예시:
[semgrep]
...
기존 규칙을 수정하고 사용자 정의 규칙셋을 합성하는 구성 섹션을 만들지 않도록 주의하십시오. 후자는 미리 정의된 규칙을 완전히 대체합니다.
[$analyzer]
구성 섹션
[$analyzer]
섹션을 사용하여 분석기의 동작을 사용자 정의할 수 있습니다. 유효한 속성은 구성하는 종류에 따라 다릅니다.
설정 | 적용 대상 | 설명 |
---|---|---|
[[$analyzer.ruleset]]
| 미리 정의된 규칙 | 기존 규칙을 수정하는 내용을 정의합니다. |
interpolate
| 모든 |
true 로 설정되면 구성에서 환경 변수를 평가할 수 있습니다. 이 기능을 사용할 때는 비밀이나 토큰이 누출되지 않도록 주의하세요. (기본값: 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
| 미리 정의된 규칙에서 사용되는 식별자의 값 |
귀하는 분석기의 CI 작업에서 생성된 gl-sast-report.json
을 보고 type
및 value
값을 확인하여 이 섹션에 제공해야 합니다.
이 파일은 분석기의 작업 아티팩트로 다운로드할 수 있습니다.
예를 들어 아래 스니펫은 셋세마 섹션에 제공해야 하는 semgrep
규칙의 식별자 세 개를 보여줍니다. JSON 객체의 type
및 value
키는 이 섹션에서 제공해야 하는 값과 해당됩니다.
...
"vulnerabilities": [
{
"id": "7331a4b7093875f6eb9f6eb1755b30cc792e9fb3a08c9ce673fb0d2207d7c9c9",
"category": "sast",
"message": "Key Exchange without Entity Authentication",
"description": "Audit the use of 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 Rule 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 )
|
구성 예시:
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.override]
severity = "Critical"
name = "Command injection"
...
[[$analyzer.passthrough]]
섹션
nodejs-scan
및 semgrep
분석기만 지원합니다.[[$analyzer.passthrough]]
섹션을 사용하면 분석기에 대한 사용자 정의 구성을 합성할 수 있습니다. 각 분석기당 최대 20개의 이러한 섹션을 정의할 수 있습니다. Passthrough는 사전에 정의된 분석기의 규칙을 대체하는 완전한 구성으로 평가되며 _passthrough 연쇄_로 구성됩니다.
Passthrough는 순서대로 평가됩니다. 연쇄에 나중에 나열된 Passthrough가 더 높은 우선순위를 갖으며 이전 Passthrough에 의해 생성된 데이터를 덮어쓰거나 추가할 수 있습니다(mode
에 따라 달라짐). 기존 구성을 사용하거나 수정해야 하는 경우 유용합니다.
단일 Passthrough에 의해 생성된 데이터의 양은 1MB로 제한됩니다.
설정 | 적용 대상 | 설명 |
---|---|---|
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를 사용하여 구성을 가져옵니다. |
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"
nodejs-scan
을 위한 raw passthrough를 사용하여 사용자 정의 구성 합성
다음 사용자 정의 규칙 구성으로,nodejs-scan
분석기의 사전 정의된 동작이 사용자 정의 구성으로 대체되었습니다.
value
에 사용된 구문은 njsscan 구성 형식을 따릅니다.
[nodejs-scan]
description = "nodejs-scan의 내 사용자 정의 규칙셋"
[[nodejs-scan.passthrough]]
type = "raw"
value = '''
---
- nodejs-extensions:
- .js
template-extensions:
- .new
- .hbs
- ''
ignore-filenames:
- skip.js
ignore-paths:
- __MACOSX
- skip_dir
- node_modules
ignore-extensions:
- .hbs
ignore-rules:
- regex_injection_dos
- pug_jade_template
- express_xss
'''
semgrep
를 위한 파일 통과를 사용하여 사용자 정의 구성을 합성하십시오.
다음 사용자 정의 규칙 집합 구성으로 semgrep
분석기의 미리 정의된 규칙집합이 리포지터리내에 있는 my-semgrep-rules.yaml
라는 파일에 포함된 사용자 정의 규칙집합으로 교체됩니다.
# my-semgrep-rules.yml
---
rules:
- id: my-custom-rule
pattern: print("Hello World")
message: |
Hello World의 무단 사용.
severity: ERROR
languages:
- python
[semgrep]
description = "Semgrep를 위한 내 사용자 정의 규칙집합"
[[semgrep.passthrough]]
type = "file"
value = "my-semgrep-rules.yml"
semgrep
를 위한 연결된 통과를 사용하여 사용자 정의 구성을 합성하십시오.
다음 사용자 정의 규칙 집합 구성으로, semgrep
분석기의 미리 정의된 규칙집합이 네 개의 연속된 통과를 평가하여 생성된 사용자 정의 규칙집합으로 교체됩니다. 각 통과는 컨테이너 내의 /sgrules
디렉터리에 쓰여지는 파일을 생성합니다. Git 원본이 응답하지 않을 경우 60초의 timeout
가 설정됩니다.
이 예제에서 다양한 통과 유형을 보여줍니다:
- 두 개의
git
통과, 첫 번째는myrules
Git 리포지터리에서develop
브랜치를 풀링하고, 두 번째는sast-rules
리포지터리에서 revision97f7686
를 풀링하며go
하위 디렉터리에 있는 파일만을 고려합니다.-
sast-rules
항목은 설정을 덮어씁니다. 왜냐하면 설정이 뒤에 나타나기 때문입니다. - 두 체크아웃 사이에 파일명 충돌이 있는 경우,
sast-rules
리포지터리의 파일이myrules
리포지터리의 파일을 덮어씁니다.
-
-
raw
통과는value
를/sgrules/insecure.yml
에 씁니다. -
url
통과는 URL에서 호스팅되는 구성을 가져와/sgrules/gosec.yml
에 씁니다.
그 후, 마지막 구성을 사용하여 /sgrules
아래에 위치한 Semgrep를 호출합니다.
[semgrep]
description = "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이 감지됨
metadata:
cwe: "CWE-200: 미인가된 사용자에게 민감한 정보 노출"
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 = "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' 감지됨
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: |
하드 코딩된 비밀번호 사용
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
"""
# /sgrules/my-rules.yml
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function 'insecure' 감지됨
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: |
하드 코딩된 비밀번호 사용
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"