Semgrep SAST Citizen Developer —
Semgrep SAST
Semgrep SAST Static Analysis Security Citizen Developer Custom Rules CI/CD Integration Pattern Matching Vulnerability Scanning Open Source Production
| Tool | Type | Languages | Speed | Custom Rules | Cost |
|---|---|---|---|---|---|
| Semgrep | SAST | 30+ | เร็วมาก | YAML ง่าย | Free OSS / Paid App |
| SonarQube | SAST + Quality | 25+ | ปานกลาง | Java plugin | Free CE / Paid |
| CodeQL | SAST | 10+ | ช้า | QL language | Free for OSS |
| Snyk Code | SAST | 15+ | เร็ว | Limited | Free tier / Paid |
| Bandit | SAST (Python) | Python only | เร็ว | Python plugin | Free |
| ESLint Security | SAST (JS) | JS/TS only | เร็ว | JS rules | Free |
Getting Started
# === Semgrep Installation and Usage ===
# Install
# pip install semgrep
# OR
# brew install semgrep
# Quick scan with auto config (3000+ rules)
# semgrep --config auto .
# Scan with specific ruleset
# semgrep --config p/python .
# semgrep --config p/javascript .
# semgrep --config p/owasp-top-ten .
# semgrep --config p/security-audit .
# Scan single file
# semgrep --config auto app.py
# Output formats
# semgrep --config auto --json -o results.json .
# semgrep --config auto --sarif -o results.sarif .
# Common rulesets:
# p/python — Python security rules
# p/javascript — JavaScript security rules
# p/typescript — TypeScript security rules
# p/owasp-top-ten — OWASP Top 10 vulnerabilities
# p/security-audit — Comprehensive security audit
# p/secrets — Hardcoded secrets detection
# p/ci — CI-optimized ruleset
from dataclasses import dataclass
@dataclass
class SemgrepFinding:
rule_id: str
severity: str
file: str
line: int
message: str
fix: str
findings = [
SemgrepFinding("python.lang.security.audit.exec-detected", "WARNING",
"app.py", 42, "Detected use of exec() which can lead to code injection",
"Use ast.literal_eval() for safe evaluation"),
SemgrepFinding("python.django.security.injection.sql-injection", "ERROR",
"views.py", 85, "SQL injection via string formatting in raw query",
"Use parameterized queries: cursor.execute(sql, [param])"),
SemgrepFinding("python.lang.security.audit.hardcoded-password", "WARNING",
"config.py", 12, "Hardcoded password detected in source code",
"Use environment variables: os.environ.get('DB_PASSWORD')"),
SemgrepFinding("javascript.express.security.xss.reflected-xss", "ERROR",
"routes/api.js", 23, "User input directly rendered without sanitization",
"Use DOMPurify or escape output before rendering"),
]
print("=== Semgrep Scan Results ===")
for f in findings:
print(f" [{f.severity}] {f.rule_id}")
print(f" File: {f.file}:{f.line}")
print(f" Issue: {f.message}")
print(f" Fix: {f.fix}")
Custom Rules
=== Custom Semgrep Rules ===
rules/sql-injection.yaml
rules:
- id: custom-sql-injection
pattern: |
cursor.execute($QUERY)
pattern-not: |
cursor.execute($QUERY, $PARAMS)
message: >
SQL query without parameterized arguments detected.
Use cursor.execute(query, [params]) to prevent SQL injection.
severity: ERROR
languages: [python]
metadata:
category: security
owasp: A03:2021 Injection
- id: custom-hardcoded-secret
patterns:
- pattern: |
$VAR = "..."
- metavariable-regex:
metavariable: $VAR
regex: (password|secret|api_key|token|auth)
message: >
Possible hardcoded secret in variable '$VAR'.
Use environment variables instead.
severity: WARNING
languages: [python]
- id: custom-insecure-random
pattern: random.random()
fix: secrets.token_hex(32)
message: >
Using random.random() for security purposes is insecure.
Use secrets module instead.
severity: WARNING
languages: [python]
Test custom rules:
semgrep --config rules/ --test
Run custom rules:
semgrep --config rules/ src/
@dataclass
class CustomRule:
rule_id: str
pattern: str
severity: str
category: str
languages: str
rules = [
CustomRule("no-eval", "eval($X)", "ERROR", "Code Injection", "python javascript"),
CustomRule("no-exec", "exec($X)", "ERROR", "Code Injection", "python"),
CustomRule("sql-injection", "cursor.execute(f'...')", "ERROR", "Injection", "python"),
CustomRule("hardcoded-secret", "$VAR = '...' (regex: password|key)", "WARNING", "Secrets", "python javascript"),
CustomRule("insecure-random", "random.random()", "WARNING", "Crypto", "python"),
CustomRule("no-debugger", "debugger", "WARNING", "Debug Code", "javascript"),
CustomRule("open-redirect", "redirect(request.args.get(...))", "ERROR", "Redirect", "python"),
]
print("\n=== Custom Rules Library ===")
for r in rules:
print(f" [{r.rule_id}] Severity: {r.severity} | Category: {r.category}")
print(f" Pattern: {r.pattern}")
print(f" Languages: {r.languages}")
CI/CD Integration
=== CI/CD Pipeline Integration ===
GitHub Actions
.github/workflows/semgrep.yml
name: Semgrep Security Scan
on: [pull_request]
jobs:
semgrep:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/secrets
generateSarif: true
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: semgrep.sarif
CircleCI
.circleci/config.yml
jobs:
security-scan:
docker:
- image: returntocorp/semgrep
steps:
- checkout
- run:
name: Semgrep Scan
command: semgrep ci --config auto
GitLab CI
.gitlab-ci.yml
semgrep:
image: returntocorp/semgrep
script:
- semgrep ci --config auto
rules:
- if: $CI_MERGE_REQUEST_IID
@dataclass
class PolicyConfig:
severity: str
action: str
notify: str
auto_fix: bool
policies = [
PolicyConfig("CRITICAL", "Block PR / Block Deploy", "Slack #security + PagerDuty", False),
PolicyConfig("ERROR", "Block PR", "Slack #security + Comment on PR", False),
PolicyConfig("WARNING", "Comment on PR", "Slack #dev-alerts", False),
PolicyConfig("INFO", "Log only", "Dashboard only", False),
]
print("Security Policy:")
for p in policies:
print(f" [{p.severity}] Action: {p.action}")
print(f" Notify: {p.notify}")
เคล็ดลับ
- Auto: เริ่มด้วย --config auto สแกน 3000+ Rules ทันที
- CI: ใส่ Semgrep ใน CI/CD ทุก PR อัตโนมัติ
- Custom: เขียน Custom Rule สำหรับ Pattern เฉพาะองค์กร
- Policy: กำหนด Policy ว่า Severity ไหน Block Deploy
- False Positive: ใช้ pattern-not ลด False Positive
Semgrep SAST คืออะไร
Static Analysis Security Open Source สแกนช่องโหว่โค้ด 30+ ภาษา Pattern Matching YAML Rule Registry 3000+ CI/CD Pipeline เร็ว Monorepo