규칙 집합 사용자 정의

Tier: Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated
  • 활성화됨: GitLab 16.2에서 모호한 패스스루 참조를 지정하는 지원.

해당 리포지토리에서 스캔하는 동안 규칙 집합 구성 파일을 정의함으로써 SAST 분석기의 동작을 사용자 정의할 수 있습니다. 사용자 정의의 두 가지 유형이 있습니다:

고급 SAST는 미리 정의된 규칙의 동작을 수정하는 것만 지원하며, 미리 정의된 규칙을 교체하는 것은 지원하지 않습니다.

미리 정의된 규칙 비활성화

모든 SAST 분석기에 대해 미리 정의된 규칙을 비활성화할 수 있습니다.

규칙을 비활성화하면:

Semgrep 기반 분석기는 비활성화된 규칙을 다르게 처리합니다:

  • 성능 향상을 위해, Semgrep 기반 분석기는 비활성화된 규칙을 전혀 스캔하지 않습니다.
  • Semgrep 기반 분석기에서 규칙을 비활성화하면, 해당 규칙에 대한 기존 취약점 발견 사항은 sast-ruleset.toml 파일을 기본 브랜치에 병합한 후 자동으로 해결됩니다.

이 동작을 구성하는 방법에 대한 정보는 스키마예제 섹션을 참조하십시오.

미리 정의된 규칙 재정의

특정 미리 정의된 규칙의 속성은 모든 SAST 분석기에 대해 재정의할 수 있습니다. 이는 SAST를 기존 워크플로우나 도구에 맞추는 데 유용할 수 있습니다. 예를 들어, 조직 정책에 따라 취약점의 심각도를 재정의하거나 취약점 보고서에 표시될 다른 메시지를 선택할 수 있습니다.

이 동작을 구성하는 방법에 대한 정보는 스키마예제 섹션을 참조하십시오.

사용자 정의 구성 만들기

Semgrep 기반 분석기에 대해 GitLab 유지 관리 규칙 집합을 자신의 규칙으로 교체할 수 있습니다.

패스스루를 통해 사용자 정의를 제공하며, 이는 런타임에 패스스루 체인으로 구성되고 평가되어 완전한 구성을 생성합니다. 그런 다음 기본 스캐너가 이 새로운 구성에 대해 실행됩니다.

파일을 리포지토리에 커밋하거나 규칙 집합 구성 파일 내에 인라인으로 사용하는 등의 다양한 방법으로 구성을 제공할 수 있는 여러 유형의 패스스루가 있습니다. 또한 체인 내에서 후속 패스스루가 어떻게 처리될지 선택할 수 있으며, 이전 구성을 덮어쓰거나 추가할 수 있습니다.

이 동작을 구성하는 방법에 대한 정보는 스키마예제 섹션을 참조하십시오.

구성 파일 작성

규칙 세트 구성 파일을 작성하려면:

  1. 프로젝트의 루트에 .gitlab 디렉터리를 생성합니다. 디렉터리가 아직 존재하지 않는 경우에만 생성합니다.
  2. .gitlab 디렉터리에 sast-ruleset.toml이라는 파일을 생성합니다.

원격 구성 파일 지정

현재 리포지토리 외부에 저장된 규칙 세트 구성 파일을 사용하기 위해 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"

고급 사용법을 위해 비공식 원격 구성 예제를 참조하세요.

원격 구성 파일 문제 해결

원격 구성 파일이 사용자 지정을 올바르게 적용하지 않는 경우 원인은 다음과 같을 수 있습니다:

  1. 레포지토리에 로컬 .gitlab/sast-ruleset.toml 파일이 있습니다.
    • 기본적으로 로컬 파일이 존재하는 경우, 원격 구성이 변수로 설정되어 있어도 로컬 파일이 사용됩니다.
    • SECURE_ENABLE_LOCAL_CONFIGURATION CI/CD 변수false로 설정하여 로컬 구성 파일을 무시할 수 있습니다.
  2. 인증에 문제가 있습니다.
    • 이것이 문제의 원인인지 확인하려면 인증이 필요하지 않은 리포지토리 위치에서 구성 파일을 참조해 보세요.

스키마

최상위 섹션

최상위 섹션은 하나 이상의 _구성 섹션_을 포함하며, 이는 TOML 테이블로 정의됩니다.

설정 설명
[$analyzer] 분석기에 대한 구성 섹션을 선언합니다. 이름은 SAST 분석기 목록에 정의된 스네이크 케이스 이름을 따릅니다.

구성 예:

[semgrep]
...

기존 규칙을 수정하는 구성 섹션을 만들고 사용자 지정 규칙 세트를 구축하는 것은 피하세요.

[$analyzer] 구성 섹션

[$analyzer] 섹션을 사용하면 분석기의 동작을 사용자 지정할 수 있습니다. 유효한 속성은 만드는 구성 종류에 따라 다릅니다.

설정 적용 대상 설명
[[$analyzer.ruleset]] 미리 정의된 규칙 기존 규칙에 대한 수정을 정의합니다.
interpolate 모든 true로 설정하면 환경 변수를 평가하기 위해 구성 내에서 $VAR를 사용할 수 있습니다. 이 기능은 비밀이나 토큰이 유출되지 않도록 주의해서 사용하세요. (기본값: false)
description 패스스루 사용자 지정 규칙 세트의 설명입니다.
targetdir 패스스루 최종 구성이 저장되어야 하는 디렉터리입니다. 비어 있으면 랜덤 이름의 디렉터리가 생성됩니다. 디렉터리는 최대 100MB의 파일을 포함할 수 있습니다.
validate 패스스루 true로 설정하면 각 패스스루의 내용이 검증됩니다. 검증은 yaml, xml, jsontoml 내용에 대해 작동합니다. 적절한 검증기는 [[$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 미리 정의된 규칙에서 사용되는 식별자의 값입니다.

올바른 typevalue의 값을 보려면 애널라이저에 의해 생성된 gl-sast-report.json을 확인하면 됩니다. 이 파일은 애널라이저의 CI 작업에서 작업 아티팩트로 다운로드할 수 있습니다.

예를 들어, 아래 코드 조각은 세 개의 식별자를 가진 semgrep 규칙의 발견을 보여줍니다. JSON 객체의 typevalue 키는 이 섹션에서 제공해야 하는 값에 해당합니다.

...
  "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는 분석기에 의해 채워지지만 namedescription을 대신하여 더 이상 사용되지 않음으로 표시되었습니다.

구성 예시:

[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_idgosec.G106-1 또는 cwe322인 규칙.
  • sobelow 규칙 중 sobelow_rule_idsql_injection인 규칙.
  • flawfinder 규칙 중 flawfinder_func_namememcpy인 규칙.
[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"

데모 프로젝트

데모 프로젝트는 이러한 구성 옵션 중 일부를 설명합니다.

이러한 프로젝트 중 많은 부분은 원격 규칙 세트를 사용하여 규칙을 오버라이드하거나 비활성화하는 방법을 보여주며, 어떤 분석기를 위한 것인지에 따라 그룹화되어 있습니다.

원격 규칙 세트를 설정하는 과정을 설명하는 비디오 데모도 있습니다: