Semgrep静态代码分析Skill semgrep

Semgrep是一种快速静态代码分析工具,专门用于检测代码中的安全漏洞和编码标准问题。它支持多种编程语言,易于集成到CI/CD流程中,帮助开发团队在早期发现和修复漏洞。关键词:静态分析、代码安全、漏洞检测、CI/CD集成、Semgrep工具。

测试 0 次安装 0 次浏览 更新于 3/24/2026

name: semgrep type: tool description: > Semgrep是一个快速的静态分析工具,用于查找漏洞和执行代码标准。 适用于扫描代码中的安全问题或集成到CI/CD管道中。

Semgrep

Semgrep是一个高效的静态分析工具,用于查找低复杂度漏洞和定位特定代码模式。由于其易用性、无需构建代码、内置多个规则以及方便的定制规则创建,它通常是审计代码库时首先运行的工具。此外,Semgrep在CI/CD管道中的集成使其成为确保代码质量的良好选择。

主要好处:

  • 防止已知漏洞和安全漏洞的重新出现
  • 支持大规模代码重构,例如升级已弃用的API
  • 轻松集成到CI/CD管道中
  • 自定义Semgrep规则模拟实际代码的语义
  • 允许在不与第三方共享代码的情况下进行安全扫描
  • 扫描通常只需几分钟(而不是几小时或几天)
  • 易于使用,适合开发人员和安全专业人员

何时使用

使用Semgrep时:

  • 寻找易于识别模式的漏洞
  • 分析单个文件(过程内分析)
  • 检测系统性漏洞(代码库中的多个实例)
  • 强制执行安全默认值和代码标准
  • 执行快速初始安全评估
  • 扫描代码前无需构建

考虑替代方案时:

  • 需要分析多个文件 → 考虑Semgrep Pro Engine或CodeQL
  • 需要复杂流程分析 → 考虑CodeQL
  • 需要跨文件的高级污染跟踪 → 考虑CodeQL或Semgrep Pro
  • 自定义内部框架分析 → 可能需要专门工具

快速参考

任务 命令
使用自动检测扫描 semgrep --config auto
使用特定规则集扫描 semgrep --config="p/trailofbits"
使用自定义规则扫描 semgrep -f /path/to/rules
输出到SARIF格式 semgrep -c p/default --sarif --output scan.sarif
测试自定义规则 semgrep --test
禁用指标 semgrep --metrics=off --config=auto
按严重性筛选 semgrep --config=auto --severity ERROR
显示数据流追踪 semgrep --dataflow-traces -f rule.yml

安装

先决条件

  • Python 3.7 或更高版本(用于pip安装)
  • macOS、Linux 或 Windows
  • Homebrew(可选,用于macOS/Linux)

安装步骤

通过Python包安装器:

python3 -m pip install semgrep

通过Homebrew(macOS/Linux):

brew install semgrep

通过Docker:

docker pull returntocorp/semgrep

保持Semgrep更新

# 检查当前版本
semgrep --version

# 通过pip更新
python3 -m pip install --upgrade semgrep

# 通过Homebrew更新
brew upgrade semgrep

验证

semgrep --version

核心工作流程

步骤 1: 初始扫描

使用自动配置扫描评估Semgrep的有效性:

semgrep --config auto

重要: 自动模式在线提交指标。要禁用:

export SEMGREP_SEND_METRICS=off
# 或
semgrep --metrics=off --config auto

步骤 2: 选择目标规则集

使用Semgrep Registry选择规则集:

# 安全重点规则集
semgrep --config="p/trailofbits"
semgrep --config="p/cwe-top-25"
semgrep --config="p/owasp-top-ten"

# 语言特定
semgrep --config="p/javascript"

# 多个规则集
semgrep --config="p/trailofbits" --config="p/r2c-security-audit"

步骤 3: 审查和分类结果

按严重性筛选结果:

semgrep --config=auto --severity ERROR

使用输出格式以便于分析:

# SARIF用于VS Code SARIF Explorer
semgrep -c p/default --sarif --output scan.sarif

# JSON用于自动化
semgrep -c p/default --json --output scan.json

步骤 4: 配置忽略文件

创建.semgrepignore文件以排除路径:

# 忽略特定文件/目录
path/to/ignore/file.ext
path_to_ignore/

# 按扩展名忽略
*.ext

# 包含.gitignore模式
:include .gitignore

注意: 默认情况下,Semgrep跳过/tests/test/vendors文件夹。

如何定制

编写自定义规则

Semgrep规则是带有模式匹配语法的YAML文件。基本结构:

rules:
  - id: rule-id
    languages: [go]
    message: 一些消息
    severity: ERROR # INFO / WARNING / ERROR
    pattern: test(...)

运行自定义规则

# 单个文件
semgrep --config custom_rule.yaml

# 规则目录
semgrep --config path/to/rules/

关键语法参考

语法/操作符 描述 示例
... 匹配零个或多个参数/语句 func(..., arg=value, ...)
$X, $VAR 元变量(捕获并跟踪值) $FUNC($INPUT)
<... ...> 深层表达式操作符(嵌套匹配) if <... user.is_admin() ...>:
pattern-inside 仅在上下文中匹配 循环内的模式
pattern-not 排除特定模式 负匹配
pattern-either 逻辑OR(任何模式匹配) 多个替代方案
patterns 逻辑AND(所有模式匹配) 组合条件
metavariable-pattern 嵌套元变量约束 约束捕获的值
metavariable-comparison 比较元变量值 $X > 1337

示例:检测不安全请求验证

rules:
  - id: requests-verify-false
    languages: [python]
    message: requests.get 使用 verify=False 禁用 SSL 验证
    severity: WARNING
    pattern: requests.get(..., verify=False, ...)

示例:SQL注入的污染模式

rules:
  - id: sql-injection
    mode: taint
    pattern-sources:
      - pattern: request.args.get(...)
    pattern-sinks:
      - pattern: cursor.execute($QUERY)
    pattern-sanitizers:
      - pattern: int(...)
    message: 潜在SQL注入,用户输入未经净化
    languages: [python]
    severity: ERROR

测试自定义规则

创建带注释的测试文件:

# ruleid: requests-verify-false
requests.get(url, verify=False)

# ok: requests-verify-false
requests.get(url, verify=True)

运行测试:

semgrep --test ./path/to/rules/

对于自动修复测试,创建.fixed文件(例如,test.pytest.fixed.py):

semgrep --test
# 输出: 1/1: ✓ 所有测试通过
#         1/1: ✓ 所有修复测试通过

配置

配置文件

Semgrep不需要中央配置文件。配置通过以下方式完成:

  • 命令行标志
  • 环境变量
  • .semgrepignore用于路径排除

忽略模式

在仓库根目录创建.semgrepignore

# 忽略目录
tests/
vendor/
node_modules/

# 忽略文件类型
*.min.js
*.generated.go

# 包含.gitignore模式
:include .gitignore

抑制误报

添加内联注释以抑制特定发现:

# nosemgrep: rule-id
risky_function()

最佳实践:

  • 指定确切的规则ID(而非通用的# nosemgrep
  • 解释为什么禁用该规则
  • 报告误报以改进规则

自定义规则中的元数据

包含元数据以提供更好上下文:

rules:
  - id: example-rule
    metadata:
      cwe: "CWE-89"
      confidence: HIGH
      likelihood: MEDIUM
      impact: HIGH
      subcategory: vuln
    # ... 规则其余部分

高级用法

技巧和窍门

技巧 为什么有帮助
使用--time标志 识别慢规则和文件以优化
限制省略号使用 减少误报并提高性能
使用pattern-inside作为上下文 创建更清晰、更集中的发现
启用自动补全 加速命令行工作流程
使用focus-metavariable 在输出中高亮特定代码位置

扫描非标准扩展

强制语言解释不常见的文件扩展名:

semgrep --config=/path/to/config --lang python --scan-unknown-extensions /path/to/file.xyz

数据流追踪

使用--dataflow-traces理解值如何流向发现:

semgrep --dataflow-traces -f taint_rule.yml test.py

示例输出:

污染来源于:
  test.py
    2┆ data = get_user_input()

污染到达汇点的方式:
  test.py
    3┆ return output(data)

多语言文件扫描

扫描嵌入语言(例如HTML中的JavaScript):

rules:
  - id: eval-in-html
    languages: [html]
    message: JavaScript中的eval
    patterns:
      - pattern: <script ...>$Y</script>
      - metavariable-pattern:
          metavariable: $Y
          language: javascript
          patterns:
            - pattern: eval(...)
    severity: WARNING

常量传播

匹配元变量持有特定值的实例:

rules:
  - id: high-value-check
    languages: [python]
    message: $X 高于 1337
    patterns:
      - pattern: function($X)
      - metavariable-comparison:
          metavariable: $X
          comparison: $X > 1337
    severity: WARNING

自动修复功能

为规则添加自动修复:

rules:
  - id: ioutil-readdir-deprecated
    languages: [golang]
    message: ioutil.ReadDir 已弃用。使用 os.ReadDir 替代。
    severity: WARNING
    pattern: ioutil.ReadDir($X)
    fix: os.ReadDir($X)

预览修复而不应用:

semgrep -f rule.yaml --dryrun --autofix

应用修复:

semgrep -f rule.yaml --autofix

性能优化

分析性能:

semgrep --config=auto --time

优化规则:

  1. 使用paths缩小文件范围
  2. 最小化省略号使用
  3. 使用pattern-inside首先建立上下文
  4. 移除不必要的元变量

管理第三方规则

使用semgrep-rules-manager收集第三方规则:

pip install semgrep-rules-manager
mkdir -p $HOME/custom-semgrep-rules
semgrep-rules-manager --dir $HOME/custom-semgrep-rules download
semgrep -f $HOME/custom-semgrep-rules

CI/CD集成

GitHub Actions

推荐方法

  1. 主要分支上的全面扫描使用广泛规则集(计划任务)
  2. 针对拉取请求的差异感知扫描使用聚焦规则
  3. 阻止带有未解决发现的PR(一旦成熟)

示例工作流程

name: Semgrep
on:
  pull_request: {}
  push:
    branches: ["master", "main"]
  schedule:
    - cron: '0 0 1 * *' # 每月

jobs:
  semgrep-schedule:
    if: ((github.event_name == 'schedule' || github.event_name == 'push' || github.event.pull_request.merged == true)
        && github.actor != 'dependabot[bot]')
    name: Semgrep默认扫描
    runs-on: ubuntu-latest
    container:
      image: returntocorp/semgrep
    steps:
      - name: 检出主要仓库
        uses: actions/checkout@v4
      - run: semgrep ci
        env:
          SEMGREP_RULES: p/default

  semgrep-pr:
    if: (github.event_name == 'pull_request' && github.actor != 'dependabot[bot]')
    name: Semgrep PR扫描
    runs-on: ubuntu-latest
    container:
      image: returntocorp/semgrep
    steps:
      - uses: actions/checkout@v4
      - run: semgrep ci
        env:
          SEMGREP_RULES: >
            p/cwe-top-25
            p/owasp-top-ten
            p/r2c-security-audit
            p/trailofbits

在CI中添加自定义规则

规则在同一仓库中:

env:
  SEMGREP_RULES: p/default custom-semgrep-rules-dir/

规则在私有仓库中:

env:
  SEMGREP_PRIVATE_RULES_REPO: semgrep-private-rules
steps:
  - name: 检出主要仓库
    uses: actions/checkout@v4
  - name: 检出私有自定义Semgrep规则
    uses: actions/checkout@v4
    with:
      repository: ${{ github.repository_owner }}/${{ env.SEMGREP_PRIVATE_RULES_REPO }}
      token: ${{ secrets.SEMGREP_RULES_TOKEN }}
      path: ${{ env.SEMGREP_PRIVATE_RULES_REPO }}
  - run: semgrep ci
    env:
      SEMGREP_RULES: ${{ env.SEMGREP_PRIVATE_RULES_REPO }}

在CI中测试规则

name: 测试Semgrep规则

on: [push, pull_request]

jobs:
  semgrep-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
        with:
          python-version: "3.11"
          cache: "pip"
      - run: python -m pip install -r requirements.txt
      - run: semgrep --test --test-ignore-todo ./path/to/rules/

常见错误

错误 为什么错误 正确方法
在私有代码上使用--config auto 向Semgrep服务器发送元数据 使用--metrics=off或特定规则集
忘记.semgrepignore 扫描排除目录如/vendor 创建.semgrepignore文件
不测试带有误报的规则 规则产生噪音 添加# ok:测试案例
使用通用的# nosemgrep 使代码审查更困难 使用# nosemgrep: rule-id并附解释
过度使用省略号... 降低性能和准确性 尽可能使用特定模式
不在规则中包含元数据 使分类困难 添加CWE、置信度、影响字段

限制

  • 单文件分析: 没有Semgrep Pro Engine时无法跨文件跟踪数据流
  • 无需构建: 无法分析编译代码或解析动态依赖项
  • 基于模式: 可能错过需要深度语义理解的漏洞
  • 有限的污染跟踪: 复杂污染分析仍在发展中
  • 自定义框架: 内部专有框架可能支持不佳

相关技能

技能 何时一起使用
codeql 用于跨文件污染跟踪和复杂数据流分析
sarif-parsing 用于在管道中处理Semgrep SARIF输出

资源

关键外部资源

Trail of Bits公共Semgrep规则 社区贡献的Semgrep规则用于安全审计,带有贡献指南和质量标准。

Semgrep Registry 官方Semgrep规则注册表,可按语言、框架和安全类别搜索。

Semgrep Playground 交互式在线工具用于编写和测试Semgrep规则。使用“简单模式”便于模式组合。

学习Semgrep语法 全面的Semgrep规则编写基础指南。

Trail of Bits博客:如何向组织介绍Semgrep 组织采用Semgrep的七步计划,包括试点测试、推广和CI/CD集成。

Trail of Bits博客:使用Semgrep发现goroutine泄漏 编写自定义规则检测Go特定问题的真实世界示例。

视频资源