When to Use
- Writing custom Semgrep rules for project-specific vulnerability patterns
- Creating detection rules for internal APIs or frameworks
- Building taint-mode rules to track data flow from sources to sinks
- Porting detection logic from other tools to Semgrep
- Defining coding standards as enforceable rules
When NOT to Use
- Running existing Semgrep scans (use the semgrep sub-skill in static-analysis)
- Complex interprocedural analysis (use CodeQL for deep data flow)
- Binary or bytecode analysis
Rule Template
rules:
- id: <org>-<category>-<specific-issue>
languages: [<language>]
message: >
<Clear description of the issue and remediation>
severity: ERROR # ERROR | WARNING | INFO
metadata:
cwe: "CWE-XXX: Description"
confidence: HIGH # HIGH | MEDIUM | LOW
category: security
patterns:
- pattern: <vulnerable-code-pattern>
- pattern-not: <safe-variant-to-exclude>
Pattern Operators
| Operator | Use Case |
|---|---|
pattern |
Match exact code structure |
patterns |
All must match (AND) |
pattern-either |
Any matches (OR) |
pattern-not |
Exclude matches |
pattern-inside |
Only match within context |
pattern-not-inside |
Only match outside context |
pattern-regex |
Regex on source text |
metavariable-regex |
Regex on captured variable |
metavariable-comparison |
Numeric/string comparison |
Taint Mode Template
rules:
- id: <taint-rule-id>
languages: [<language>]
message: "Untrusted data flows to dangerous sink"
severity: ERROR
mode: taint
pattern-sources:
- pattern: <source-of-untrusted-data>
pattern-sinks:
- pattern: <dangerous-function-call>
pattern-sanitizers:
- pattern: <function-that-makes-input-safe>
Testing Rules
Create test files with annotations:
def test_vulnerable():
# ruleid: my-rule-id
dangerous_call(user_input)
def test_safe():
# ok: my-rule-id
safe_call(sanitized_input)
semgrep --test rules/
Best Practices
- Use specific, descriptive rule IDs with org prefix
- Include CWE and confidence metadata
- Write clear remediation guidance in the message
- Always create test cases for true positives AND false positives
- Use
pattern-notto reduce false positives - Prefer
pattern-insideto limit scope rather than overly complex patterns - Test against real codebases before deploying to CI
Resources
- Rule Syntax — https://semgrep.dev/docs/writing-rules/rule-syntax/
- Playground — https://semgrep.dev/playground
- Rule Registry — https://semgrep.dev/explore