🤖 Kelos Strategist Agent @gjkim42
Summary
Security vulnerability backlogs grow faster than most teams can triage and fix them. GitHub already sends structured webhook events for Dependabot alerts, CodeQL findings, and secret scanning alerts — but Kelos's githubWebhook source currently cannot extract security-specific fields from these events, limiting its usefulness for automated vulnerability remediation.
This proposal outlines a security vulnerability auto-remediation pipeline that leverages Kelos's existing webhook infrastructure and task pipeline capabilities, identifies the specific code gap preventing it from working today, and provides concrete example configurations.
Motivation
- Scale problem: A single critical CVE can affect hundreds of dependencies across an organization. Manual triage and patching doesn't scale.
- Speed problem: Mean time to remediation for known vulnerabilities is often weeks or months. Automated agents could cut this to hours.
- Natural fit for Kelos: The multi-stage pipeline pattern (triage → fix → validate → PR) maps directly to Kelos's
dependsOn task chains.
- Target audience: Security-conscious teams, regulated industries (fintech, healthcare), open source maintainers, DevSecOps teams.
Current State Analysis
What works today
The githubWebhook source in kelos-webhook-server can already:
- Receive any GitHub webhook event type — the
Events field is an untyped string array (api/v1alpha1/taskspawner_types.go:322)
- Verify webhook signatures via
X-Hub-Signature-256
- Pass events through filters (action, author, excludeAuthors)
- Create Tasks from matched events
You can configure a TaskSpawner to listen for dependabot_alert events today:
when:
githubWebhook:
events: ["dependabot_alert"]
filters:
- event: "dependabot_alert"
action: "created"
What doesn't work
ParseGitHubWebhook (internal/webhook/github_filter.go:40-187) has explicit handling for 6 event types:
IssuesEvent, PullRequestEvent, IssueCommentEvent
PullRequestReviewEvent, PullRequestReviewCommentEvent, PushEvent
For any other event type (including all security events), it falls into the default case (lines 171-184) which only extracts sender and action from raw JSON. This means:
{{.Title}} → empty (no alert title extraction)
{{.Body}} → empty (no alert description or CVE details)
{{.URL}} → empty (no link to the alert)
{{.Number}} → 0 (no alert number)
{{.ID}} → empty (no alert identifier)
The agent would receive a prompt with no context about what vulnerability to fix.
What go-github v66 supports
The go-github v66 library (already a dependency in go.mod) parses these security event types via github.ParseWebHook():
| Event type |
Go type |
Key fields |
dependabot_alert |
*github.DependabotAlertEvent |
Alert.SecurityAdvisory (CVE, CVSS, description), Alert.SecurityVulnerability (package, severity, version range), Alert.HTMLURL |
code_scanning_alert |
*github.CodeScanningAlertEvent |
Alert.Rule (ID, description, severity), Alert.MostRecentInstance (location, message), Alert.HTMLURL |
secret_scanning_alert |
*github.SecretScanningAlertEvent |
Alert.SecretType, Alert.Secret (redacted), Alert.HTMLURL |
These types are already parsed correctly by github.ParseWebHook() on line 41 of github_filter.go — the data is available but discarded because there are no case branches for them.
Proposal
1. Extend ParseGitHubWebhook for security events
Add case branches for DependabotAlertEvent, CodeScanningAlertEvent, and SecretScanningAlertEvent in internal/webhook/github_filter.go. Map their fields to the standard template variables:
| Template variable |
dependabot_alert mapping |
code_scanning_alert mapping |
{{.ID}} |
Alert number |
Alert number |
{{.Title}} |
Advisory summary |
Rule description |
{{.Body}} |
Advisory description + CVE + severity + affected package |
Rule full description + instance message + location |
{{.URL}} |
Alert HTML URL |
Alert HTML URL |
{{.Number}} |
Alert number |
Alert number |
Additionally, expose security-specific fields via the {{.Payload}} variable (which already passes RawEvent), so prompt templates can access:
{{.Payload.Alert.SecurityAdvisory.CVEID}}
{{.Payload.Alert.SecurityVulnerability.Package.Name}}
{{.Payload.Alert.SecurityVulnerability.Severity}}
2. Example: Single-stage vulnerability fixer
A minimal TaskSpawner that creates a fix PR for each new Dependabot alert:
apiVersion: kelos.dev/v1alpha1
kind: TaskSpawner
metadata:
name: security-fixer
spec:
when:
githubWebhook:
events: ["dependabot_alert"]
repository: "myorg/myrepo"
filters:
- event: "dependabot_alert"
action: "created"
maxConcurrency: 2
taskTemplate:
type: claude-code
credentials:
type: api-key
secretRef:
name: claude-credentials
workspaceRef:
name: my-workspace
branch: "security/fix-{{.ID}}"
promptTemplate: |
A new security vulnerability has been detected.
## Alert Details
- **Title**: {{.Title}}
- **URL**: {{.URL}}
## Description
{{.Body}}
## Task
1. Identify the affected dependency and vulnerable code paths
2. Update the dependency to a patched version
3. Run `make test` to verify nothing breaks
4. If tests fail, investigate and fix the breakage
5. Commit changes and create a PR referencing this alert
Keep changes minimal — only update what is needed to remediate the vulnerability.
ttlSecondsAfterFinished: 3600
metadata:
labels:
kelos.dev/trigger: "security"
3. Example: Multi-stage remediation pipeline
For high-severity vulnerabilities, a pipeline with triage, fix, and validation stages:
# Stage 1: Triage — assess severity and impact
apiVersion: kelos.dev/v1alpha1
kind: Task
metadata:
name: triage-vuln
spec:
type: claude-code
credentials:
type: api-key
secretRef:
name: claude-credentials
workspaceRef:
name: my-workspace
branch: "security/vuln-{{.ID}}"
prompt: |
A security vulnerability has been reported: {{.Title}}
Details: {{.Body}}
Analyze this vulnerability:
1. Search the codebase for usage of the affected dependency
2. Determine if the vulnerable code path is reachable
3. Assess the blast radius (which services/endpoints are affected)
Output your findings as a structured summary.
---
# Stage 2: Fix — apply the remediation
apiVersion: kelos.dev/v1alpha1
kind: Task
metadata:
name: fix-vuln
spec:
type: claude-code
credentials:
type: api-key
secretRef:
name: claude-credentials
workspaceRef:
name: my-workspace
branch: "security/vuln-{{.ID}}"
dependsOn:
- triage-vuln
prompt: |
The triage stage found that the vulnerability "{{.Title}}" affects this codebase.
Triage output: {{index .Deps "triage-vuln" "Results" "branch"}}
Apply the fix:
1. Update the affected dependency to a patched version
2. Adapt any code that relied on changed APIs
3. Run `make build` and `make test` to verify
4. Commit and push changes
---
# Stage 3: Validate — run extended checks and create PR
apiVersion: kelos.dev/v1alpha1
kind: Task
metadata:
name: validate-and-pr
spec:
type: claude-code
credentials:
type: api-key
secretRef:
name: claude-credentials
workspaceRef:
name: my-workspace
branch: "security/vuln-{{.ID}}"
dependsOn:
- fix-vuln
prompt: |
The vulnerability fix has been applied on branch {{index .Deps "fix-vuln" "Results" "branch"}}.
Validate the fix:
1. Run the full test suite: `make test`
2. Verify the vulnerable dependency version is no longer present
3. Check that no new vulnerabilities were introduced by the update
If everything passes, create a PR:
- Title: "fix(security): remediate {{.Title}}"
- Reference the original alert URL
- Label with `security` and `priority/critical`
Scope of Code Changes
The core enablement is small and focused:
internal/webhook/github_filter.go: Add ~40 lines of case branches in ParseGitHubWebhook for *github.DependabotAlertEvent, *github.CodeScanningAlertEvent, and *github.SecretScanningAlertEvent
internal/webhook/github_filter_test.go: Add test cases for each security event type
- Example: Add
examples/12-security-remediation/ with a TaskSpawner config and README
No CRD changes, no controller changes, no new dependencies.
Relationship to Existing Issues
🤖 Kelos Strategist Agent @gjkim42
Summary
Security vulnerability backlogs grow faster than most teams can triage and fix them. GitHub already sends structured webhook events for Dependabot alerts, CodeQL findings, and secret scanning alerts — but Kelos's
githubWebhooksource currently cannot extract security-specific fields from these events, limiting its usefulness for automated vulnerability remediation.This proposal outlines a security vulnerability auto-remediation pipeline that leverages Kelos's existing webhook infrastructure and task pipeline capabilities, identifies the specific code gap preventing it from working today, and provides concrete example configurations.
Motivation
dependsOntask chains.Current State Analysis
What works today
The
githubWebhooksource inkelos-webhook-servercan already:Eventsfield is an untyped string array (api/v1alpha1/taskspawner_types.go:322)X-Hub-Signature-256You can configure a TaskSpawner to listen for
dependabot_alertevents today:What doesn't work
ParseGitHubWebhook(internal/webhook/github_filter.go:40-187) has explicit handling for 6 event types:IssuesEvent,PullRequestEvent,IssueCommentEventPullRequestReviewEvent,PullRequestReviewCommentEvent,PushEventFor any other event type (including all security events), it falls into the
defaultcase (lines 171-184) which only extractssenderandactionfrom raw JSON. This means:{{.Title}}→ empty (no alert title extraction){{.Body}}→ empty (no alert description or CVE details){{.URL}}→ empty (no link to the alert){{.Number}}→ 0 (no alert number){{.ID}}→ empty (no alert identifier)The agent would receive a prompt with no context about what vulnerability to fix.
What
go-githubv66 supportsThe
go-githubv66 library (already a dependency ingo.mod) parses these security event types viagithub.ParseWebHook():dependabot_alert*github.DependabotAlertEventcode_scanning_alert*github.CodeScanningAlertEventsecret_scanning_alert*github.SecretScanningAlertEventThese types are already parsed correctly by
github.ParseWebHook()on line 41 ofgithub_filter.go— the data is available but discarded because there are nocasebranches for them.Proposal
1. Extend
ParseGitHubWebhookfor security eventsAdd
casebranches forDependabotAlertEvent,CodeScanningAlertEvent, andSecretScanningAlertEventininternal/webhook/github_filter.go. Map their fields to the standard template variables:dependabot_alertmappingcode_scanning_alertmapping{{.ID}}{{.Title}}{{.Body}}{{.URL}}{{.Number}}Additionally, expose security-specific fields via the
{{.Payload}}variable (which already passesRawEvent), so prompt templates can access:{{.Payload.Alert.SecurityAdvisory.CVEID}}{{.Payload.Alert.SecurityVulnerability.Package.Name}}{{.Payload.Alert.SecurityVulnerability.Severity}}2. Example: Single-stage vulnerability fixer
A minimal TaskSpawner that creates a fix PR for each new Dependabot alert:
3. Example: Multi-stage remediation pipeline
For high-severity vulnerabilities, a pipeline with triage, fix, and validation stages:
Scope of Code Changes
The core enablement is small and focused:
internal/webhook/github_filter.go: Add ~40 lines ofcasebranches inParseGitHubWebhookfor*github.DependabotAlertEvent,*github.CodeScanningAlertEvent, and*github.SecretScanningAlertEventinternal/webhook/github_filter_test.go: Add test cases for each security event typeexamples/12-security-remediation/with a TaskSpawner config and READMENo CRD changes, no controller changes, no new dependencies.
Relationship to Existing Issues
githubWebhooksource