Skip to content

Fix AI provider fallback + CI vet error, add multi-finding AI report - #32

Merged
h0tak88r merged 1 commit into
masterfrom
testing
Jun 7, 2026
Merged

Fix AI provider fallback + CI vet error, add multi-finding AI report#32
h0tak88r merged 1 commit into
masterfrom
testing

Conversation

@h0tak88r

@h0tak88r h0tak88r commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the failing CI pipeline, fixes an AI-provider gap introduced when OpenCode became the default, and adds a multi-finding AI report feature.

What changed

CI fix (the failing pipeline)

CGO_ENABLED=1 go vet ./... was failing with:

internal/scanner/zerodays/zerodays.go:588: address format "%s:%d" does not work with IPv6 (passed to net.Dial)

The MongoDB dial address now uses net.JoinHostPort(host, strconv.Itoa(port)) instead of fmt.Sprintf("%s:%d", ...), which is IPv6-safe. Replicated the full CI sequence locally — go vet, go build, go test ./... (all CGO_ENABLED=1) — all pass.

AI provider fallback

The dashboard "validate finding" and "report" helpers required OpenRouter specifically (openRouterChat, hardcoded openai/gpt-4o-mini). After OpenCode became the default free provider, a user who set only OPENCODE_API_KEY got "No OpenRouter API key configured."

New aiChat() helper tries OpenRouter first (UI X-OpenRouter-Key header or OPENROUTER_API_KEY), then falls back to the shared brain.ChatWithAI chain (OpenCode → Z.ai → Gemini). apiValidateFinding and apiReportFinding now use it.

Multi-finding AI report (new feature)

  • Backend: POST /api/findings/report-batch (apiReportFindingsBatch) accepts 1..N selected findings (capped at 25), builds a prompt from each finding's target/type/severity/module/evidence, and uses an attacker-mindset system prompt that enforces the exact ## Title / ## Summary / ## Steps to Reproduce / ## Impact structure (one report per finding, separated by ---; merges same-class findings). Routed through aiChat, so it works on any configured provider.
  • Frontend (scan-detail.js): new "Report selected (AI)" toolbar button that reuses the existing finding checkboxes + select-all, collects the checked rows (with file/line/url/match evidence from raw), POSTs them, and shows the generated report in a copyable modal (Copy / Close / Esc).

Programs cache hardening

programsCacheEnabled() gates the DB-backed programs cache on DB_HOST. Without a DB, the handler skips the cache + background refresh and just does a live fetch — preventing a DB-less deployment from looping expensive ~1000-call upstream rebuilds that can never be persisted.

Reviewer notes

  • testing was already merged to master earlier, so this PR is just the one new commit on top.
  • No schema changes. No new dependencies.
  • Verified locally: CGO_ENABLED=1 go vet ./..., go build, go test ./... all green; node --check on the modified JS passes.

🤖 Generated with Claude Code

…ard, vet fix

AI provider fallback:
- ui_api.go adds aiChat(): tries OpenRouter (UI header key or OPENROUTER_API_KEY)
  then falls back to the shared brain.ChatWithAI chain (OpenCode -> Z.ai -> Gemini).
  apiValidateFinding and apiReportFinding now use it, so an OpenCode-only setup no
  longer fails with "No OpenRouter API key configured".

Multi-finding AI report:
- New POST /api/findings/report-batch (apiReportFindingsBatch): accepts 1..N
  selected findings (capped at 25), builds a prompt from each finding's
  target/type/severity/module/evidence, and uses an attacker-mindset system
  prompt enforcing the Title/Summary/Steps-to-Reproduce/Impact structure
  (one report per finding, separated by ---). Routed through aiChat.
- scan-detail.js: new "Report selected (AI)" toolbar button reusing the existing
  finding checkboxes; collects checked rows, POSTs them, and shows the generated
  report in a copyable modal (Copy / Close / Esc).

Programs cache hardening:
- programsCacheEnabled() gates the DB-backed cache on DB_HOST. Without a DB the
  handler now skips cache + background refresh entirely and just does a live
  fetch, preventing a DB-less deployment from looping expensive upstream rebuilds
  that can never be persisted.

CI fix:
- zerodays.go: use net.JoinHostPort instead of fmt.Sprintf("%s:%d", ...) for the
  MongoDB dial address. Fixes `CGO_ENABLED=1 go vet ./...` failing with
  "address format %s:%d does not work with IPv6".

CI replicated locally: go vet, go build, go test all pass (CGO_ENABLED=1).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@h0tak88r
h0tak88r merged commit 67e1cfd into master Jun 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant