Mask the target URL in delivery errors, SSRF logs and log page data (closes #118)
All checks were successful
check / check (push) Successful in 3m30s

A delivery target URL is itself a credential: a Slack incoming
webhook URL is a bearer token. Three paths still reproduced it
in full.

Transport failures were the worst of them. net/http embeds the
request URL in every *url.Error it returns, so any DNS, TLS,
timeout or dial failure wrote the whole webhook URL into
DeliveryResult.Error — on disk, in the per-webhook database,
behind a json tag that a REST API would serialize.

maskURL moves to url_mask.go and is exported as MaskURL, and
maskURLError joins it: it rebuilds the *url.Error with the URL
masked, keeping the operation and the wrapped cause, so a
refused connection still reads differently from a DNS failure
or a timeout and errors.Is/As/Timeout still work. It is applied
where the errors are raised — executeHTTPRequest, shared by the
Slack and HTTP targets, and the request-construction paths — so
downstream wrapping is safe by construction. url.Parse embeds
the URL too, so ValidateTargetURL's parse branch gets the same
treatment; its error is logged and shown.

The SSRF rejection log now records only the masked URL, and
loadTargetMap hands the event log page TargetViews and a
delivery projection instead of raw target rows, so the stored
config blob has no path to that template either.
This commit is contained in:
clawbot
2026-08-11 12:52:05 +00:00
committed by sneak
parent 84b758b785
commit b6529f45a9
9 changed files with 468 additions and 45 deletions

View File

@@ -26,14 +26,14 @@ const (
)
// seedConfiguredTarget inserts a target with a stored config
// blob.
// blob and returns it.
func seedConfiguredTarget(
t *testing.T,
db *database.Database,
webhookID string,
targetType database.TargetType,
config string,
) {
) *database.Target {
t.Helper()
tgt := &database.Target{
@@ -48,6 +48,8 @@ func seedConfiguredTarget(
t,
db.DB().Omit(clause.Associations).Create(tgt).Error,
)
return tgt
}
// renderSourceDetailPage runs the real source detail handler