# Implementing Semgrep For Custom Sast Rules

> 使用 YAML 编写自定义 Semgrep SAST 规则，以检测应用程序特定漏洞、执行编码标准并集成到 CI/CD 管道中。

- Skill: `killvxk/implementing-semgrep-for-custom-sast-rules` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add killvxk/implementing-semgrep-for-custom-sast-rules`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/implementing-semgrep-for-custom-sast-rules/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/implementing-semgrep-for-custom-sast-rules

---


# 使用 Semgrep 实施自定义 SAST 规则

## 概述

Semgrep 是一个开源静态分析工具，使用模式匹配来发现漏洞、执行代码标准并检测安全漏洞。自定义规则使用 Semgrep 的模式语法以 YAML 编写，无需编译器知识即可使用。支持 30+ 种语言，包括 Python、JavaScript、Go、Java 和 C。

## 前置条件

- Python 3.8+ 或 Docker
- 已安装 Semgrep CLI
- 支持语言的目标代码库

## 安装

```bash
# 通过 pip 安装
pip install semgrep

# 通过 Homebrew 安装
brew install semgrep

# 通过 Docker 运行
docker run -v "${PWD}:/src" returntocorp/semgrep semgrep --config auto /src

# 验证
semgrep --version
```

## 运行 Semgrep

```bash
# 自动检测代码规则
semgrep --config auto .

# 使用 Semgrep 注册表规则
semgrep --config r/python.lang.security

# 使用自定义规则文件
semgrep --config my-rules.yaml .

# 使用多个配置
semgrep --config auto --config ./custom-rules/ .

# JSON 输出
semgrep --config auto --json . > results.json

# SARIF 输出（用于 GitHub）
semgrep --config auto --sarif . > results.sarif

# 按严重性过滤
semgrep --config auto --severity ERROR .
```

## 编写自定义规则

### 基本模式匹配

```yaml
# rules/sql-injection.yaml
rules:
  - id: sql-injection-string-format
    languages: [python]
    severity: ERROR
    message: |
      Potential SQL injection via string formatting.
      Use parameterized queries instead.
    pattern: |
      cursor.execute(f"..." % ...)
    metadata:
      cwe: ["CWE-89"]
      owasp: ["A03:2021"]
      category: security
    fix: |
      cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
```

### 模式运算符

```yaml
rules:
  - id: hardcoded-secret-in-code
    languages: [python, javascript, typescript]
    severity: ERROR
    message: Hardcoded secret detected in source code
    patterns:
      - pattern-either:
          - pattern: $VAR = "..."
          - pattern: $VAR = '...'
      - metavariable-regex:
          metavariable: $VAR
          regex: (?i)(password|secret|api_key|token|aws_secret)
      - pattern-not: $VAR = ""
      - pattern-not: $VAR = "changeme"
      - pattern-not: $VAR = "PLACEHOLDER"
    metadata:
      cwe: ["CWE-798"]
      category: security
```

### 污点分析

```yaml
rules:
  - id: xss-taint-tracking
    languages: [python]
    severity: ERROR
    message: User input flows to HTML response without sanitization
    mode: taint
    pattern-sources:
      - pattern: request.args.get(...)
      - pattern: request.form.get(...)
      - pattern: request.form[...]
    pattern-sinks:
      - pattern: return render_template_string(...)
      - pattern: Markup(...)
    pattern-sanitizers:
      - pattern: bleach.clean(...)
      - pattern: escape(...)
    metadata:
      cwe: ["CWE-79"]
      owasp: ["A03:2021"]
```

### 多语言规则

```yaml
rules:
  - id: insecure-random
    languages: [python, javascript, go, java]
    severity: WARNING
    message: |
      Using insecure random number generator. Use cryptographically
      secure alternatives for security-sensitive operations.
    pattern-either:
      # Python
      - pattern: random.random()
      - pattern: random.randint(...)
      # JavaScript
      - pattern: Math.random()
      # Go
      - pattern: math/rand.Intn(...)
      # Java
      - pattern: new java.util.Random()
    metadata:
      cwe: ["CWE-330"]
```

### 执行编码标准

```yaml
rules:
  - id: require-error-handling
    languages: [go]
    severity: WARNING
    message: Error return value not checked
    pattern: |
      $VAR, _ := $FUNC(...)
    fix: |
      $VAR, err := $FUNC(...)
      if err != nil {
        return fmt.Errorf("$FUNC failed: %w", err)
      }

  - id: no-console-log-in-production
    languages: [javascript, typescript]
    severity: WARNING
    message: Remove console.log before merging to production
    pattern: console.log(...)
    paths:
      exclude:
        - "tests/*"
        - "*.test.*"
```

### JWT 安全规则

```yaml
rules:
  - id: jwt-none-algorithm
    languages: [python]
    severity: ERROR
    message: JWT decoded without algorithm verification - allows token forgery
    patterns:
      - pattern: jwt.decode($TOKEN, ..., algorithms=["none"], ...)
    metadata:
      cwe: ["CWE-347"]

  - id: jwt-no-verification
    languages: [python]
    severity: ERROR
    message: JWT decoded with verification disabled
    patterns:
      - pattern: jwt.decode($TOKEN, ..., options={"verify_signature": False}, ...)
    metadata:
      cwe: ["CWE-345"]
```

## 规则测试

```yaml
# rules/test-sql-injection.yaml
rules:
  - id: sql-injection-format-string
    languages: [python]
    severity: ERROR
    message: SQL injection via format string
    pattern: |
      cursor.execute(f"...{$VAR}...")

# 测试文件中的注解：
# test-sql-injection.py
def bad_query(user_id):
    # ruleid: sql-injection-format-string
    cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")

def good_query(user_id):
    # ok: sql-injection-format-string
    cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
```

```bash
# 运行规则测试
semgrep --test rules/

# 测试特定规则
semgrep --config rules/sql-injection.yaml --test
```

## CI/CD 集成

### GitHub Actions

```yaml
name: Semgrep SAST
on: [pull_request]

jobs:
  semgrep:
    runs-on: ubuntu-latest
    container:
      image: returntocorp/semgrep
    steps:
      - uses: actions/checkout@v4

      - name: Run Semgrep
        run: |
          semgrep --config auto \
            --config ./custom-rules/ \
            --sarif --output results.sarif \
            --severity ERROR \
            .

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: results.sarif
```

### GitLab CI

```yaml
semgrep:
  stage: test
  image: returntocorp/semgrep
  script:
    - semgrep --config auto --config ./custom-rules/ --json --output semgrep.json .
  artifacts:
    reports:
      sast: semgrep.json
```

## 配置文件

```yaml
# .semgrep.yaml
rules:
  - id: my-org-rules
    # ... rules here

# .semgrepignore
tests/
node_modules/
vendor/
*.min.js
```

## 最佳实践

1. **从 auto 配置开始**，然后为组织特定模式添加自定义规则
2. **使用 `# ruleid:` 和 `# ok:` 注解测试规则**
3. **对数据流漏洞（XSS、SQLi、SSRF）使用污点模式**
4. **包含元数据**（CWE、OWASP）用于漏洞分类
5. **在可能的情况下通过 `fix` 键提供修复建议**
6. **排除测试文件**以减少误报
7. **在共享仓库中对规则进行版本控制**
8. **在 CI 中作为 ERROR 严重性发现的阻塞检查运行**

