mcpField
O
opengrep

opengrep

github.com/opengrep安全1893 次安装37 周前更新
代码仓库

关于 opengrep

Opengrep 是从 Semgrep 分叉的开源静态分析和结构化代码搜索命令行工具。开发者可沿用 Semgrep 规则,扫描安全问题或匹配代码模式。

主要功能

  1. 01基于 AST 的结构化代码搜索
  2. 02使用规则集进行安全扫描
  3. 03自定义 YAML 规则与污点分析
  4. 04输出 SARIF 和 JSON
  5. 05规则测试与校验
  6. 06支持 Windows

适用场景

  1. 01查找特定调用并减少文本搜索噪声
  2. 02扫描代码中的常见漏洞
  3. 03追踪不可信数据流向风险操作
  4. 04应用自定义规则前进行测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/opengrep/skills --skill opengrep

安装后在 Claude Code 中输入/opengrep确认已加载。

详细介绍

Opengrep 静态分析

Opengrep 是一个由社区维护的开源静态分析工具,分叉自 Semgrep。它使用相同的规则语法和 CLI 接口,因此现有 Semgrep 规则和知识可以迁移使用。

两种使用场景

1. 语义代码搜索(grep 的替代方案)

探索代码库时,grep 可以查找文本模式,但会遗漏结构模式。Opengrep 能理解代码结构:

任务GrepOpengrep
查找文本“execute”快速有效大材小用
查找 cursor.execute(...) 调用可能匹配注释和字符串只匹配实际调用
查找调用 os.system 的函数很难pattern-inside + pattern
查找未参数化的 SQL 查询几乎不可能污点模式

在以下情况下使用 Opengrep:

  • 需要查找带有特定参数的函数/方法调用
  • grep 返回了过多误报(匹配到注释、字符串或相似名称)
  • 需要查找特定上下文中的模式(循环内、try 块内)
  • 模式具有结构含义,而不只是文本

在以下情况下继续使用 grep:

  • 简单的文本搜索
  • 速度至关重要
  • 模式是字面字符串或简单正则表达式
2. 安全扫描

运行规则集以检测漏洞和不安全模式。

安装

Linux / macOS
curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh | bash
Windows(PowerShell)
irm https://raw.githubusercontent.com/opengrep/opengrep/main/install.ps1 | iex
手动安装

从发布页面下载二进制文件。

验证
opengrep --version

macOS、Linux 和 Windows 均提供独立运行的二进制文件。无需 Python。

运行 opengrep scan --help 可查看所有可用选项和标志。

代码搜索模式

快速单行命令
# Find all calls to a function
opengrep scan -e 'dangerous_function(...)' -l python .

# Find method calls on specific objects
opengrep scan -e '$OBJ.execute(...)' -l python .

# Find assignments to a variable name
opengrep scan -e '$VAR = os.environ.get(...)' -l python .

# Find function definitions
opengrep scan -e 'def $FUNC(...): ...' -l python .
性能说明

Opengrep 会将整个文件解析为 AST。进行快速文本搜索时,grep 的速度要快 10 到 100 倍。只有在结构匹配值得付出额外开销时,才使用 Opengrep。

安全扫描

快速扫描
# Scan with a ruleset
opengrep scan --config p/security-audit .

# Multiple rulesets
opengrep scan --config p/security-audit --config p/owasp-top-ten .

# Scan specific paths
opengrep scan --config p/python src/
输出格式
# SARIF for tooling
opengrep scan --config p/default --sarif -o results.sarif .

# JSON for automation
opengrep scan --config p/default --json -o results.json .

# Show data flow traces
opengrep scan --dataflow-traces -f rule.yaml .

# Include enclosing context (function/class) in JSON output (experimental)
opengrep scan --output-enclosing-context --json -f rule.yaml . --experimental
筛选
# By severity
opengrep scan --config p/default --severity ERROR .

# By path
opengrep scan --config p/default --include='src/**' --exclude='**/test/**' .

# Apply exclusions to explicitly passed file targets (not just directory scan roots)
opengrep scan --force-exclude --exclude='**/vendor/**' -f rule.yaml vendor/lib.py
文件内跨函数污点追踪

Opengrep 支持在文件内跨函数追踪污点:

opengrep scan --taint-intrafile -f taint-rule.yaml .

这使高阶函数支持成为可能,类似于 Semgrep Pro 的 --pro-intrafile。

编写自定义规则

基本规则结构
rules:
  - id: hardcoded-secret
    languages: [python]
    message: "Hardcoded secret detected in $VAR"
    severity: ERROR
    patterns:
      - pattern: $VAR = "$VALUE"
      - metavariable-regex:
          metavariable: $VALUE
          regex: ^sk_live_
规则 ID 唯一性

重要:在一个配置中,所有规则的 ID 必须唯一。如果多条规则共用同一个 ID,由于加载规则时会进行去重,因此只会使用其中一条。

编写针对多种语言的规则时,这一点尤其重要。即使规则针对不同语言,也不能重复使用同一个规则 ID:

# WRONG - both rules have id: taint, only one will be active
rules:
  - id: taint
    languages: [python]
    pattern: dangerous_call(...)
    # ...

  - id: taint
    languages: [rust]
    pattern: unsafe_fn(...)
    # ...
# CORRECT - unique IDs for each rule
rules:
  - id: taint-python-dangerous-call
    languages: [python]
    pattern: dangerous_call(...)
    # ...

  - id: taint-rust-unsafe-fn
    languages: [rust]
    pattern: unsafe_fn(...)
    # ...

使用包含语言或上下文信息的描述性 ID,以避免冲突。

模式语法
语法含义
...匹配零个或多个参数/语句
$VAR元变量(捕获任意表达式)
$...ARGS省略号元变量(捕获零个或多个参数)
<... $X ...>深层表达式匹配(嵌套)
模式运算符
运算符用途
pattern匹配精确模式
patterns必须全部匹配(AND)
pattern-either任意一个匹配即可(OR)
pattern-not排除匹配项
pattern-inside必须位于上下文中
pattern-not-inside不得位于上下文中
pattern-regex正则表达式匹配
metavariable-regex按正则表达式筛选捕获值
metavariable-comparison比较捕获值
组合模式
rules:
  - id: dangerous-deserialization
    languages: [python]
    message: "Unsafe pickle load on potentially untrusted data"
    severity: ERROR
    patterns:
      - pattern-either:
          - pattern: pickle.load(...)
          - pattern: pickle.loads(...)
      - pattern-not-inside: |
          def $FUNC(...):
            ...
污点模式

用于跟踪从源到汇的数据流:

rules:
  - id: sql-injection
    languages: [python]
    message: "User input flows to SQL query without parameterization"
    severity: ERROR
    mode: taint
    pattern-sources:
      - pattern: request.args.get(...)
      - pattern: request.form[...]
    pattern-sinks:
      - pattern: cursor.execute($QUERY, ...)
        focus-metavariable: $QUERY
    pattern-sanitizers:
      - pattern: int(...)
      - pattern: escape(...)

污点分析的关键概念:

  • 源:不可信数据进入的位置
  • 汇:数据变得危险的位置
  • 净化器:使数据变得安全的内容
YAML 易错点

模式是 YAML 字符串值。任何包含 : (冒号加空格)的模式都会被误解为 YAML 映射,并导致验证错误。请务必为这类模式加引号:

# BROKEN -- YAML parser sees "shell: true" as a nested mapping
- pattern: spawn($CMD, { ..., shell: true, ... })

# CORRECT -- quoted string, parsed as a single pattern value
- pattern: "spawn($CMD, { ..., shell: true, ... })"

常见触发内容:shell: true、mode: 0o777、redirect: "follow"、error: $ERR。不确定时,请为模式加引号。

对于同时包含双引号和冒号的模式,请使用转义的内部引号:

- pattern: "fetch($URL, { ..., redirect: \"follow\", ... })"
扫描非代码文件(通用语言)

对于 XML 配置、YAML 流水线、Dockerfile 和其他非代码文件,结构化模式可能无法生效。请使用 languages: [generic] 搭配 pattern-regex:

rules:
  - id: cleartext-traffic
    patterns:
      - pattern-regex: 'cleartextTrafficPermitted\s*=\s*"true"'
    languages: [generic]
    severity: WARNING
    paths:
      include:
        - "app/src/"

paths 键可限制规则适用的文件:

paths:
  include:
    - ".github/workflows/"    # Only scan GHA workflow files
  exclude:
    - "test/"                 # Skip test directories

注意:虽然存在 languages: [dockerfile],但 pattern-not-inside 在多个 Dockerfile 指令间无法可靠工作。对于跨多行的 Dockerfile 安全检查,建议使用 generic 搭配正则表达式。

metavariable-pattern

使用 metavariable-pattern 限制元变量可匹配的内容。它必须作为列表项放在 patterns: 内,与捕获该元变量的模式并列:

rules:
  - id: dynamic-property-assignment
    patterns:
      - pattern: $OBJ[$KEY] = $VALUE
      - metavariable-pattern:
          metavariable: $KEY
          patterns:
            - pattern-not: "..."    # Exclude literal string keys
    languages: [typescript, javascript]
    severity: WARNING

这与 metavariable-regex 不同,后者按正则表达式而非模式进行筛选。

模式解析限制

某些语言结构无法作为独立片段进行匹配:

  • catch 块:单独使用 catch ($ERR) { ... } 无效。必须包含 try:try { ... } catch ($ERR) { ... }。即便如此,catch 代码块中复杂的省略号在 TypeScript 中仍可能无法解析。
  • 变通方法:直接匹配危险表达式,而不是将其放在 try/catch 上下文中。
规则选项(Opengrep 专用)
rules:
  - id: expensive-rule
    options:
      timeout: 10              # Per-rule timeout (requires --allow-rule-timeout-control)
      dynamic_timeout: true    # Scale timeout with file size
      max_match_per_file: 100  # Limit matches per file
    # ... rest of rule

使用 --allow-rule-timeout-control 启用逐规则超时设置。

测试规则

测试文件注释

在预期发现项的上一行放置 # ruleid:(对于污点规则,放在汇处之前):

# test_rule.py

def vulnerable():
    user_id = request.args.get("id")
    # ruleid: sql-injection
    cursor.execute("SELECT * FROM users WHERE id = " + user_id)

def safe():
    user_id = int(request.args.get("id"))
    # ok: sql-injection
    cursor.execute("SELECT * FROM users WHERE id = " + user_id)
运行测试
# Test a rule (supports multiple target files)
opengrep test --config rule.yaml test_file.py test_file2.py

# Validate rule syntax (positional argument, not --config)
opengrep validate rule.yaml

# Debug taint flow
opengrep scan --dataflow-traces -f rule.yaml test_file.py

配置

.semgrepignore

Opengrep 使用 .semgrepignore 以保持兼容性。通过 --semgrepignore-filename 指定自定义文件名:

# Ignore directories
vendor/
node_modules/
**/testdata/

# Ignore patterns
*.min.js
*.generated.go
行内抑制

默认注释标记:nosemgrep、nosem、noopengrep(均可使用):

password = get_from_vault()  # nosemgrep: hardcoded-password
password = get_from_vault()  # nosem: hardcoded-password
password = get_from_vault()  # noopengrep: hardcoded-password

使用 --opengrep-ignore-pattern 添加其他模式:

# Add nosec as an additional suppression annotation
opengrep scan --opengrep-ignore-pattern='nosec' -f rule.yaml .

规则元数据

rules:
  - id: command-injection
    metadata:
      category: security
      subcategory:
        - vuln              # vuln = confirmed vulnerability, audit = needs review
      cwe:
        - "CWE-78: Improper Neutralization of Special Elements used in an OS Command"
      owasp:
        - "A03:2021 - Injection"
      confidence: HIGH      # HIGH, MEDIUM, or LOW
      references:
        - https://owasp.org/Top10/A03_2021-Injection/
    # ... rest of rule

工具会使用 category/subcategory/confidence 字段对发现项进行分类和筛选。对于高置信度漏洞,请使用 subcategory: [vuln];对于需要人工审查的模式,请使用 subcategory: [audit]。

使用 --inline-metavariables 在元数据输出中包含元变量值。

常用规则集

规则集重点
p/security-audit全面的安全规则
p/owasp-top-tenOWASP Top 10 漏洞
p/cwe-top-25CWE Top 25 漏洞
p/python / p/javascript / p/golang特定语言

注意:可用的规则集可能与 Semgrep 注册表不同。

与 Semgrep 的区别

Opengrep 是从 Semgrep 1.100.0 分叉而来。主要区别:

  • 开放 Semgrep Pro 功能:文件内跨函数污点分析(--taint-intrafile)、高阶函数支持和方法间污点流——均无需商业许可证即可使用
  • 更多语言:Visual Basic(Semgrep CE 和 Pro 均不支持)、Apex、Elixir(Semgrep CE 不支持),以及增强了污点支持的 Clojure
  • Windows:原生支持
  • 单规则超时:规则选项 timeout 和 dynamic_timeout
  • 匹配数量限制:规则选项 max_match_per_file 和 CLI 标志 --max-match-per-file
  • 上下文输出:--output-enclosing-context 可显示函数/类上下文
  • 自定义忽略模式:--opengrep-ignore-pattern 可扩展默认抑制规则

完整更新日志见:https://github.com/opengrep/opengrep/blob/main/OPENGREP.md

现有的 Semgrep 规则和文档通常也适用。

资源

评论

支持 Markdown