Hari 49: AI Remediation Node — LLM Auto-Summarize Scanner Findings ke Slack
3 min read

Hari 49: AI Remediation Node — LLM Auto-Summarize Scanner Findings ke Slack

Scanner findings (Semgrep, Checkov, Trivy) otomatis di-summarize oleh LLM gratis (OpenCode Zen deepseek-v4-flash-free) dan diposting ke Slack. 3 format scanner dinormalisasi ke unified schema. Cloudflare WAF block urllib fixed.

devsecops
ai remediation
llm
opencode zen
slack integration
vulnerability management
Share

Day 48 routing Falco CRITICAL alerts ke Slack. Hari ini — LLM baca scanner finding, generate ringkasan bahaya + contoh kode perbaikan, kirim ke Slack #security-alerts. Full automation.

Arsitektur

Scanner finding JSON → POST /webhook/sast-alert
  → normalize_finding(raw, scanner)
  → IF severity in (CRITICAL, HIGH, MEDIUM):
      → call_llm() via OpenCode Zen (deepseek-v4-flash-free, $0.00)
      → post_to_slack_remediation()
  → ELSE: log only

Unified Finding Format

Setiap scanner punya JSON schema beda. Normalize ke unified format:

def normalize_finding(raw, scanner):
    if scanner == "semgrep":
        return {
            "id": raw["check_id"],
            "title": raw["check_id"].split(".")[-1],
            "severity": raw["extra"]["severity"],
            "file": f"{raw['path']}:{raw['start']['line']}",
            "description": raw["extra"]["message"],
            "references": raw["extra"]["metadata"]["references"],
        }
    elif scanner == "checkov":
        return {
            "id": raw["check_id"],
            "title": raw["check_name"],
            "severity": raw.get("severity") or "MEDIUM",
            "file": raw["file_path"],
            "description": f"Check {raw['check_id']} failed on {raw['resource']}",
            "references": [raw["guideline"]] if raw.get("guideline") else [],
        }
    elif scanner == "trivy":
        return {
            "id": raw["VulnerabilityID"],
            "title": raw.get("Title") or f"{raw['PkgName']} vulnerability",
            "severity": raw["Severity"],
            "file": raw["PkgName"],
            "description": raw["Description"],
            "references": raw.get("References", []),
        }

LLM Prompt (Bahasa Indonesia)

Berikut temuan keamanan dari scanner:
Judul: [title]
Severity: [severity]
File: [file]
Deskripsi: [description]
Referensi: [references]

Berikan:
1. Ringkasan bahaya (max 2 kalimat)
2. Contoh kode perbaikan (jika ada, singkat)

OpenCode Zen — FREE Model

Model Cost Privacy Quality
deepseek-v4-flash-free $0.00 Zero-retention Best reasoning
big-pickle $0.00 Data dipakai training Stealth
ling-3.0-flash-free $0.00 Zero-retention Fast
nemotron-3-ultra-free $0.00 Data di-log NVIDIA NVIDIA

Pilih deepseek-v4-flash-free — free, reasoning bagus, no privacy concerns.

Test Results — 3 Scanners

Test Scanner Severity Route LLM Response Slack?
1 Semgrep WARNING Log only
2 Checkov MEDIUM LLM + Slack 496 chars ✅ HTTP 200
3 Trivy CRITICAL LLM + Slack 636 chars ✅ HTTP 200

Priority routing: CRITICAL/HIGH/MEDIUM → LLM + Slack. WARNING/NOTICE/LOW → log only (save LLM cost).

Slack Message Format

🤖 *AI Remediation: Ensure no security groups allow ingress from 0.0.0.0:0 to port 80*
*Scanner:* checkov | *Severity:* MEDIUM | *File:* terraform/main.tf
*AI Analysis:*
[LLM-generated ringkasan bahaya + contoh kode perbaikan]

Cloudflare WAF vs Python urllib

Problem: urllib.request default User-Agent Python-urllib/3.x → Cloudflare block (HTTP 403, error code 1010)

Fix: Tambah custom User-Agent header:

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {OPENCODE_ZEN_API_KEY}",
    "User-Agent": "SecureBank-WebhookReceiver/1.0",  # ← fix
}

Pelajaran Hari Ini

Scanner format normalization. Semgrep, Checkov, Trivy — semua beda JSON schema. Unified format simplifies downstream processing. Satu normalize_finding() function, 3 branches.

OpenCode Zen free models. 7 model gratis, deepseek-v4-flash-free paling bagus. OpenAI-compatible API — tinggal ganti base URL + model name. $0.00 cost.

Cloudflare blocks default urllib User-Agent. Selalu tambah custom User-Agent di urllib requests ke public APIs. Python-urllib/3.x = bot signature = blocked.

Priority routing saves cost. WARNING/NOTICE/LOW skip LLM call entirely. Hanya CRITICAL/HIGH/MEDIUM yang kena LLM. Hemat token, hemat waktu.

Repo

Semua code dan dokumentasi ada di: https://github.com/stayrelevantid/chalange-devsecops

Kesimpulan

Day 49 complete. AI remediation node — scanner findings auto-summarized via LLM (deepseek-v4-flash-free, $0.00) and posted to Slack. 3 scanner formats normalized (Semgrep, Checkov, Trivy). Priority routing: CRITICAL/HIGH/MEDIUM → LLM+Slack, others → log. Cloudflare WAF fix applied. Besok Day 50 — CSPM (Prowler/ScoutSuite).

Enjoyed this article? Share it!

Share

Diskusi & Komentar

Artikel Terkait