사용자 정의 규칙 집합

Tier: Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

- GitLab 16.2에서 모호한 passthrough refs를 지정하는 지원을 활성화했습니다.

저희의 SAST 분석기의 동작을 구체적으로 정의하는 규칙 집합 구성 파일을 정의함으로써 커스터마이징할 수 있습니다. 두 가지 유형의 커스터마이징이 있습니다:

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

미리 정의된 규칙 비활성화

어떤 SAST 분석기의 미리 정의된 규칙을 비활성화할 수 있습니다.

규칙을 비활성화하면:

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

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

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

미리 정의된 규칙 재정의

어떤 SAST 분석기에 대한 미리 정의된 규칙의 특정 속성을 재정의할 수 있습니다. 이것은 SAST를 기존의 워크플로나 도구에 적응시킬 때 유용합니다. 예를 들어, 기관 정책에 따라 취약점의 심각도를 재정의하거나, 취약점 보고서에 표시할 다른 메시지를 선택할 수 있습니다.

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

사용자 정의 구성 빌드

Semgrep 기반 분석기를 위한 GitLab이 제공하는 규칙집합을 사용자 정의로 대체할 수 있습니다.

Passthroughs를 통해 사용자 지정을 제공하며, 이는 실행시 passthrough 체인으로 구성되어 완전한 구성을 생성하기 위해 평가됩니다. 결과적으로 기존 스캐너는 이 새로운 구성 대상으로 실행됩니다.

파일에 커밋하거나 규칙 집합 구성 파일 내부에 인라인으로 구성을 제공하는 등 다양한 passthrough 유형이 있습니다. 또한 체인 내의 이후 passthrough가 이전 구성을 덮어쓰거나 추가하는 방식을 선택할 수 있습니다.

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

구성 파일 생성

규칙 집합 구성 파일을 생성하려면:

  1. 프로젝트 루트에 .gitlab 디렉토리를 만듭니다(이미 존재하지 않는 경우).
  2. .gitlab 디렉토리에 sast-ruleset.toml라는 파일을 만듭니다.

원격 구성 파일 지정

현재 저장소 외부에 저장된 규칙 집합 구성 파일을 사용하려면 CI/CD 변수를 설정할 수 있습니다. 이를 통해 여러 프로젝트에 걸쳐 동일한 규칙을 적용할 수 있습니다.

SAST_RULESET_GIT_REFERENCE 변수는 프로젝트 URI, 선택적 인증, 선택적 Git SHA와 유사한 형식을 사용합니다. 다음 형식을 사용합니다:

[<AUTH_USER>[:<AUTH_PASSWORD>]@]<PROJECT_PATH>[@<GIT_SHA>]

참고: 만약 프로젝트에 .gitlab/sast-ruleset.toml 파일이 커밋되어 있다면 현재 저장소의 local configuration이 우선시되며 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 테이블로 정의된 하나 이상의 _구성 섹션_이 포함됩니다.

설정 설명
[$분석기] 이름은 SAST 분석기 목록에 정의된 snake-case 이름에 따라 분석기에 대한 구성 섹션을 선언합니다.

구성 예시:

[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 미리 정의된 규칙이 사용하는 식별자의 값

분석기가 생성한 gl-sast-report.json 파일을 보고 식별자의 올바른 값을 확인할 수 있습니다. 분석기의 CI 작업에서 작업 artifact로 이 파일을 다운로드할 수 있습니다.

예를 들어, 아래 스니펫은 세 가지 식별자를 가진 semgrep 규칙에서의 결과를 보여줍니다. JSON 객체의 typevalue 키는 이 섹션에서 제공해야 하는 값과 일치합니다.

...
  "vulnerabilities": [
    {
      "id": "7331a4b7093875f6eb9f6eb1755b30cc792e9fb3a08c9ce673fb0d2207d7c9c9",
      "category": "sast",
      "message": "Entity Authentication이 없는 키 교환",
      "description": "ssh.InsecureIgnoreHostKey의 사용을 감사",
      ...
      "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와 같은 유효한 옵션이 있습니다.

참고: message는 분석기가 채웁니다. 그러나 이제 namedescription을 선호하므로 폐기되었습니다.

구성 예시:

[semgrep]
  [[semgrep.ruleset]]
    [semgrep.ruleset.override]
      severity = "Critical"
      name = "명령 삽입"
    ...

[[$analyzer.passthrough]] 섹션

참고: 패스스루 구성은 Semgrep 기반 분석기에만 해당됩니다.

[[$analyzer.passthrough]] 섹션은 분석기의 사용자 지정 구성을 만들 수 있게 해줍니다. 분석기 당 최대 20개의 이러한 섹션을 정의할 수 있습니다. 패스스루는 완전한 구성으로 변환되는 _패스스루 체인_을 구성합니다. 이를 통해 분석기의 미리 정의된 규칙을 대체할 수 있습니다.

패스스루는 순서대로 평가됩니다. 체인에 나중에 나오는 패스스루가 우선적으로 처리되어 이전 패스스루에 의해 생성된 데이터를 덮어쓰거나 추가할 수 있습니다(mode에 따라 다름). 이는 기존 구성을 사용하거나 수정해야 하는 경우 유용합니다.

단일 패스스루에 의해 생성된 구성의 크기는 10MB로 제한됩니다.

설정 적용 대상 설명
type 전체 file, raw, git, url 중 하나
target 전체 패스스루 평가에 의해 작성되는 데이터를 포함하는 대상 파일. 비어 있으면 무작위 파일 이름이 사용됩니다.
mode 전체 overwrite인 경우 target 파일이 덮어쓰입니다. append인 경우 새 콘텐츠가 target 파일에 추가됩니다. git 유형은 overwrite만 지원합니다. (기본값: overwrite)
ref type = "git" 가져올 브랜치, 태그 또는 SHA의 이름을 포함
subdir type = "git" Git 저장소의 하위디렉토리를 구성 소스로 선택하는 데 사용됨
value 전체 file, url, git 유형의 경우 파일 또는 Git 저장소의 위치를 정의합니다. raw 유형의 경우 인라인 구성을 포함합니다.
validator 전체 패스스루의 평가 후 대상 파일에 대해 명시적으로 유효성 검사기(xml, yaml, json, toml)를 호출하는 데 사용됩니다.

Passthrough 유형

유형 설명
file Git 저장소에 있는 파일을 사용합니다.
raw 인라인으로 구성을 제공합니다.
git 원격 Git 저장소에서 구성을 가져옵니다.
url HTTP를 사용하여 구성을 가져옵니다.

경고: raw passthrough를 사용할 때 YAML 스니펫을 사용하는 경우 모든 들여쓰기를 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에 대한 파일 passthrough를 사용하여 사용자 지정 구성 빌드

다음 사용자 정의 규칙세트 구성으로, 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 = "Semgrep를 위한 내 사용자 정의 규칙세트"

  [[semgrep.passthrough]]
    type  = "file"
    value = "my-semgrep-rules.yml"

semgrep에 대한 passthrough 체인을 사용하여 사용자 정의 구성 빌드

다음 사용자 정의 규칙세트 구성으로, semgrep 분석기의 사전 정의된 규칙세트를 네 개의 passthrough를 평가하여 생성된 사용자 정의 규칙세트로 대체합니다. 각 passthrough는 컨테이너 내의 /sgrules 디렉터리에 쓰여지는 파일을 생성합니다. Git 원격 저장소에 반응하지 않는 경우를 대비하여 timeout을 60초로 설정합니다.

이 예시에서 다양한 passthrough 유형을 시연합니다:

  • 두 개의 git passthrough. 첫 번째는 myrules Git 저장소에서 develop 브랜치, 두 번째는 sast-rules 저장소에서 go 하위 디렉토리에 있는 97f7686 버전을 가져오고 있습니다.
    • sast-rules 항목은 구성에서 나중에 나타나기 때문에 더 높은 우선순위를 가집니다.
    • 두 체크아웃 사이에 파일명 충돌이 있는 경우, sast-rules 저장소의 파일이 myrules 저장소의 파일을 덮어씁니다.
  • raw passthrough, value/sgrules/insecure.yml에 씁니다.
  • url passthrough, URL에 호스팅된 구성을 가져와 /sgrules/gosec.yml에 씁니다.

이후 Semgrep은 /sgrules 아래에 있는 최종 구성을 사용하여 호출됩니다.

[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 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"

체인 내의 passthrough의 모드 구성

체인 내에서 발생하는 passthrough 간의 파일명 충돌을 어떻게 처리할지 선택할 수 있습니다. 기본 동작은 동일한 이름을 가진 기존 파일을 덮어쓰지만, 대신 mode = append를 선택하여 이후 파일의 내용을 이전 파일로 추가할 수 있습니다.

append 모드는 file, url, raw passthrough 유형에만 사용할 수 있습니다.

다음 사용자 정의 규칙세트 구성으로, 두 개의 raw passthrough를 사용하여 반복적으로 /sgrules/my-rules.yml 파일을 조합하고, 이 파일은 Semgrep에 규칙세트로 제공됩니다. 각 passthrough는 규칙세트에 한 개의 규칙을 추가합니다. 첫 번째 passthrough는 최상위 수준의 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' 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"

데모 프로젝트

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

이러한 프로젝트 중 많은 프로젝트는 원격 규칙 집합을 사용하여 규칙을 재정의하거나 비활성화하는 내용을 보여주며, 해당 프로젝트들은 해당 분석기에 따라 그룹화되어 있습니다.

또한 원격 규칙 집합 설정 방법을 안내하는 동영상 데모도 있습니다: