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
Citizen Developer ใช้ Semgrep อย่างไร
pip install semgrep --config auto สแกนทันที ผลลัพธ์อ่านง่าย ไฟล์ บรรทัด ช่องโหว่ วิธีแก้ Dashboard Finding Custom Rule YAML
เขียน Custom Rule อย่างไร
YAML Pattern cursor.execute message severity languages metavariable pattern-not False Positive semgrep --test --config rules/
ใช้ใน CI/CD อย่างไร
GitHub Actions CircleCI GitLab CI semgrep ci PR Block Critical Error Warning Policy SARIF GitHub Security Tab Dashboard Notification
สรุป
Semgrep SAST Citizen Developer Static Analysis Custom Rules YAML CI/CD GitHub Actions Security Scanning Pattern Matching Policy Production Vulnerability
