mirror of
https://github.com/lunchcat/sif.git
synced 2026-06-12 11:01:24 -07:00
8078978a44
ship findings to chat/webhook sinks after a scan so continuous recon can alert on what it turns up. each provider is one POST through httpx.Client, so the global proxy/rate-limit/header config applies and there's no extra http stack. config resolves env-first (SLACK_WEBHOOK_URL, DISCORD_WEBHOOK_URL, TELEGRAM_BOT_TOKEN/TELEGRAM_CHAT_ID, NOTIFY_WEBHOOK_URL), overridable by a notify-compatible yaml file so existing projectdiscovery/notify configs port over. -notify enables it, -notify-severity gates on the finding severity ladder (default medium), -notify-config points at the yaml. wired after the scan loop on the severity-filtered finding set; no provider configured is a silent no-op.
66 lines
2.7 KiB
Go
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/dropalldatabases/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)
|
|
}
|