| name | implementing-semgrep-for-custom-sast-rules |
| description | 使用 YAML 编写自定义 Semgrep SAST 规则,以检测应用程序特定漏洞、执行编码标准并集成到 CI/CD 管道中。 |
| domain | cybersecurity |
| subdomain | devsecops |
| tags | ["semgrep","sast","static-analysis","custom-rules","devsecops","code-security"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
使用 Semgrep 实施自定义 SAST 规则
概述
Semgrep 是一个开源静态分析工具,使用模式匹配来发现漏洞、执行代码标准并检测安全漏洞。自定义规则使用 Semgrep 的模式语法以 YAML 编写,无需编译器知识即可使用。支持 30+ 种语言,包括 Python、JavaScript、Go、Java 和 C。
前置条件
- Python 3.8+ 或 Docker
- 已安装 Semgrep CLI
- 支持语言的目标代码库
安装
pip install semgrep
brew install semgrep
docker run -v "${PWD}:/src" returntocorp/semgrep semgrep --config auto /src
semgrep --version
运行 Semgrep
semgrep --config auto .
semgrep --config r/python.lang.security
semgrep --config my-rules.yaml .
semgrep --config auto --config ./custom-rules/ .
semgrep --config auto --json . > results.json
semgrep --config auto --sarif . > results.sarif
semgrep --config auto --severity ERROR .
编写自定义规则
基本模式匹配
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,))
模式运算符
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
污点分析
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"]
多语言规则
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:
- pattern: random.random()
- pattern: random.randint(...)
- pattern: Math.random()
- pattern: math/rand.Intn(...)
- pattern: new java.util.Random()
metadata:
cwe: ["CWE-330"]
执行编码标准
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 安全规则
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"]
规则测试
rules:
- id: sql-injection-format-string
languages: [python]
severity: ERROR
message: SQL injection via format string
pattern: |
cursor.execute(f"...{$VAR}...")
def bad_query(user_id):
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,))
semgrep --test rules/
semgrep --config rules/sql-injection.yaml --test
CI/CD 集成
GitHub Actions
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
semgrep:
stage: test
image: returntocorp/semgrep
script:
- semgrep --config auto --config ./custom-rules/ --json --output semgrep.json .
artifacts:
reports:
sast: semgrep.json
配置文件
rules:
- id: my-org-rules
tests/
node_modules/
vendor/
*.min.js
最佳实践
- 从 auto 配置开始,然后为组织特定模式添加自定义规则
- 使用
# ruleid: 和 # ok: 注解测试规则
- 对数据流漏洞(XSS、SQLi、SSRF)使用污点模式
- 包含元数据(CWE、OWASP)用于漏洞分类
- 在可能的情况下通过
fix 键提供修复建议
- 排除测试文件以减少误报
- 在共享仓库中对规则进行版本控制
- 在 CI 中作为 ERROR 严重性发现的阻塞检查运行