id: ai-vulnerability-triage-remediation
namespace: company.security
description: |
Automated Security Triage AI Agent that analyzes CVE vulnerability reports from webhook
events or manual triggers, evaluates exploitability, extracts structured CVSS metadata,
creates GitHub tracking issues, and routes notifications to Slack based on assessed severity.
inputs:
- id: vulnerability_report
type: STRING
displayName: Vulnerability or Dependency Scan Report
defaults: |
CVE-2024-43485: Insecure deserialization in py-auth library <= 1.4.2 allows
remote unauthenticated attackers to execute arbitrary code via crafted session tokens.
Affected component: middleware/auth.py in user-service.
Attack vector: Network, Complexity: Low, Privileges Required: None.
Recommendation: Upgrade py-auth to 1.4.3 or enforce HMAC verification before decoding.
- id: target_repository
type: STRING
displayName: GitHub Target Repository (owner/repo)
defaults: my-org/user-service
- id: model_name
type: STRING
displayName: Gemini Model Name
defaults: gemini-2.0-flash
triggers:
- id: scan_webhook
type: io.kestra.plugin.core.trigger.Webhook
key: "{{ secret('WEBHOOK_KEY') }}"
tasks:
- id: security_agent_analysis
type: io.kestra.plugin.ai.agent.AIAgent
description: AI SecOps engineer analyzing CVE report and producing structured
remediation
provider:
type: io.kestra.plugin.ai.provider.GoogleGemini
apiKey: "{{ secret('GEMINI_API_KEY') }}"
modelName: "{{ trigger.body.model_name ?? inputs.model_name }}"
configuration:
temperature: 0.1
maxToken: 4096
systemMessage: |
You are a Principal Application Security Engineer. You analyze vulnerability and CVE scan reports,
extract structured metadata (CVE ID, affected component, CVSS score, verified severity: LOW/MEDIUM/HIGH/CRITICAL),
and provide actionable remediation code snippets and mitigation checklists.
Always format your output in clean Markdown with clear headings:
- ## Metadata Summary (Include bullet points for CVE_ID, AFFECTED_COMPONENT, CVSS_SCORE, ASSESSED_SEVERITY)
- ## Executive Risk Assessment
- ## Step-by-Step Remediation Plan
- ## Code Patch & Mitigation Example
- ## Verification & Testing Checklist
prompt: |
Perform a comprehensive security triage for the following finding:
TARGET REPOSITORY: {{ trigger.body.repository ?? inputs.target_repository }}
SCAN REPORT:
{{ trigger.body.report ?? inputs.vulnerability_report }}
- id: extract_triage_metadata
type: io.kestra.plugin.scripts.python.Script
description: Parses AI analysis to extract structured severity, CVE ID, and
build formatted issue body
containerImage: python:3.11-slim
inputFiles:
analysis.md: "{{ outputs.security_agent_analysis.textOutput }}"
outputFiles:
- triage_metadata.json
script: |
import json
import re
from kestra import Kestra
with open("analysis.md") as f:
content = f.read()
# Extract CVE ID
cve_match = re.search(r"CVE-\d{4}-\d{4,7}", content, re.IGNORECASE)
cve_id = cve_match.group(0).upper() if cve_match else "VULNERABILITY"
# Extract verified severity
severity = "HIGH"
if re.search(r"ASSESSED_SEVERITY[:\s*]+CRITICAL", content, re.IGNORECASE):
severity = "CRITICAL"
elif re.search(r"ASSESSED_SEVERITY[:\s*]+HIGH", content, re.IGNORECASE):
severity = "HIGH"
elif re.search(r"ASSESSED_SEVERITY[:\s*]+MEDIUM", content, re.IGNORECASE):
severity = "MEDIUM"
elif re.search(r"ASSESSED_SEVERITY[:\s*]+LOW", content, re.IGNORECASE):
severity = "LOW"
metadata = {
"cve_id": cve_id,
"severity": severity,
"repository": "{{ trigger.body.repository ?? inputs.target_repository }}",
"full_analysis": content
}
with open("triage_metadata.json", "w") as f:
json.dump(metadata, f, indent=2)
Kestra.outputs({
"cve_id": cve_id,
"severity": severity
})
- id: create_github_security_issue
type: io.kestra.plugin.github.issues.Create
description: Automatically creates a tracked security remediation issue in the
repository
oauthToken: "{{ secret('GITHUB_TOKEN') }}"
repository: "{{ trigger.body.repository ?? inputs.target_repository }}"
title: "[SECURITY] {{ outputs.extract_triage_metadata.vars.cve_id }} Triage &
Remediation Plan ({{ outputs.extract_triage_metadata.vars.severity }})"
body: |
## Automated Security Triage Report
**Target Repository:** `{{ trigger.body.repository ?? inputs.target_repository }}`
**Identified Vulnerability:** `{{ outputs.extract_triage_metadata.vars.cve_id }}`
**Assessed Severity:** **{{ outputs.extract_triage_metadata.vars.severity }}**
{{ outputs.security_agent_analysis.textOutput }}
---
*Generated automatically by Kestra AI Security Triage Workflow.*
- id: check_severity_level
type: io.kestra.plugin.core.flow.If
description: Branch based on whether vulnerability requires urgent on-call notification
condition: "{{ outputs.extract_triage_metadata.vars.severity == 'HIGH' or
outputs.extract_triage_metadata.vars.severity == 'CRITICAL' }}"
then:
- id: notify_security_slack
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: Urgent alert sent to SecOps on-call Slack channel with GitHub issue
link
url: "{{ secret('SLACK_WEBHOOK') }}"
messageText: |
🚨 *{{ outputs.extract_triage_metadata.vars.severity }} SECURITY ALERT* 🚨
*Repository:* `{{ trigger.body.repository ?? inputs.target_repository }}`
*Vulnerability:* `{{ outputs.extract_triage_metadata.vars.cve_id }}`
*Assessed Severity:* *{{ outputs.extract_triage_metadata.vars.severity }}*
*GitHub Issue:* <{{ outputs.create_github_security_issue.issueUrl }}|View Issue #{{ outputs.create_github_security_issue.issueNumber }}>
else:
- id: log_routine_finding
type: io.kestra.plugin.core.log.Log
message: "Routine vulnerability finding ({{
outputs.extract_triage_metadata.vars.cve_id }}) triaged for {{
trigger.body.repository ?? inputs.target_repository }} with severity
{{ outputs.extract_triage_metadata.vars.severity }}."