Files
sif/internal/notify/webhook.go
T
Tigah 39b333320e chore: migrate module path to github.com/vmfunc/sif (#194)
rename the go module path from github.com/dropalldatabases/sif to
github.com/vmfunc/sif across go.mod, all imports, the golangci exclude
list, release install docs and docs. pure string rename, no logic change.
2026-06-22 22:25:39 -07:00

66 lines
2.7 KiB
Go

/*
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
: :
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
: ▄█ █ █▀ · BSD 3-Clause License :
: :
: (c) 2022-2026 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
*/
package notify
import (
"context"
"net/http"
"github.com/vmfunc/sif/internal/finding"
)
// webhookProvider posts a structured json payload to an arbitrary endpoint. unlike
// the chat sinks it carries the findings as data, not a prerendered blob, so
// downstream automation (a siem, a bot, ci) keys off the fields directly.
type webhookProvider struct {
url string
}
func (w *webhookProvider) name() string { return "webhook" }
// webhookFinding is the per-item wire shape: the normalized Finding fields with
// severity flattened to its canonical string so a json consumer never sees the
// internal integer rank.
type webhookFinding struct {
Target string `json:"target"`
Module string `json:"module"`
Severity string `json:"severity"`
Key string `json:"key"`
Title string `json:"title"`
Raw string `json:"raw,omitempty"`
}
// webhookPayload wraps the batch with a count so a consumer can size buffers /
// assert completeness without walking the slice first.
type webhookPayload struct {
Count int `json:"count"`
Findings []webhookFinding `json:"findings"`
}
func (w *webhookProvider) send(ctx context.Context, client *http.Client, findings []finding.Finding) error {
items := make([]webhookFinding, 0, len(findings))
for i := 0; i < len(findings); i++ {
f := findings[i]
items = append(items, webhookFinding{
Target: f.Target,
Module: f.Module,
Severity: f.Severity.String(),
Key: f.Key,
Title: f.Title,
Raw: f.Raw,
})
}
payload := webhookPayload{Count: len(items), Findings: items}
return postJSON(ctx, client, w.url, payload)
}