SiamCafe.net Blog
Technology

Semgrep SAST Citizen Developer

semgrep sast citizen developer
Semgrep SAST Citizen Developer | SiamCafe Blog
2026-05-02· อ. บอม — SiamCafe.net· 9,056 คำ

Semgrep SAST

Semgrep SAST Static Analysis Security Citizen Developer Custom Rules CI/CD Integration Pattern Matching Vulnerability Scanning Open Source Production

ToolTypeLanguagesSpeedCustom RulesCost
SemgrepSAST30+เร็วมากYAML ง่ายFree OSS / Paid App
SonarQubeSAST + Quality25+ปานกลางJava pluginFree CE / Paid
CodeQLSAST10+ช้าQL languageFree for OSS
Snyk CodeSAST15+เร็วLimitedFree tier / Paid
BanditSAST (Python)Python onlyเร็วPython pluginFree
ESLint SecuritySAST (JS)JS/TS onlyเร็วJS rulesFree

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}")

เคล็ดลับ

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

📖 บทความที่เกี่ยวข้อง

Semgrep SAST Interview Preparationอ่านบทความ → Semgrep SAST DevOps Cultureอ่านบทความ → Semgrep SAST Microservices Architectureอ่านบทความ → Semgrep SAST Troubleshooting แก้ปัญหาอ่านบทความ → Semgrep SAST Security Hardening ป้องกันแฮกอ่านบทความ →

📚 ดูบทความทั้งหมด →