chore: pin Caddy major to v2 and document SSRF mitigations in notification service
This commit is contained in:
13
Dockerfile
13
Dockerfile
@@ -7,9 +7,16 @@ ARG BUILD_DATE
|
||||
ARG VCS_REF
|
||||
|
||||
# Allow pinning Caddy version - Renovate will update this
|
||||
# Using Caddy 2.10.2 (latest stable) to fix CVE-2025-59530 and stdlib vulnerabilities
|
||||
ARG CADDY_VERSION=2.10.2
|
||||
ARG CADDY_IMAGE=caddy:${CADDY_VERSION}-alpine
|
||||
# Build the most recent Caddy 2.x release (keeps major pinned under v3).
|
||||
# Setting this to '2' tells xcaddy to resolve the latest v2.x tag so we
|
||||
# avoid accidentally pulling a v3 major release. Renovate can still update
|
||||
# this ARG to a specific v2.x tag when desired.
|
||||
ARG CADDY_VERSION=2
|
||||
## When an official caddy image tag isn't available on the host, use a
|
||||
## plain Alpine base image and overwrite its caddy binary with our
|
||||
## xcaddy-built binary in the later COPY step. This avoids relying on
|
||||
## upstream caddy image tags while still shipping a pinned caddy binary.
|
||||
ARG CADDY_IMAGE=alpine:3.18
|
||||
|
||||
# ---- Cross-Compilation Helpers ----
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.8.0 AS xx
|
||||
|
||||
@@ -196,6 +196,19 @@ func (s *NotificationService) sendCustomWebhook(p models.NotificationProvider, d
|
||||
// resolved IP. This prevents direct user-controlled hostnames from being used
|
||||
// as the request's destination (SSRF mitigation) and helps CodeQL validate the
|
||||
// sanitisation performed by validateWebhookURL.
|
||||
//
|
||||
// NOTE (security): The following mitigations are intentionally applied to
|
||||
// reduce SSRF/request-forgery risk:
|
||||
// - `validateWebhookURL` enforces http(s) schemes and rejects private IPs
|
||||
// (except explicit localhost for testing) after DNS resolution.
|
||||
// - We perform an additional DNS resolution here and choose a non-private
|
||||
// IP to use as the TCP destination to avoid direct hostname-based routing.
|
||||
// - We set the request's `Host` header to the original hostname so virtual
|
||||
// hosting works while the actual socket connects to a resolved IP.
|
||||
// - The HTTP client disables automatic redirects and has a short timeout.
|
||||
// Together these steps make the request destination unambiguous and prevent
|
||||
// accidental requests to internal networks. If your threat model requires
|
||||
// stricter controls, consider an explicit allowlist of webhook hostnames.
|
||||
ips, err := net.LookupIP(u.Hostname())
|
||||
if err != nil || len(ips) == 0 {
|
||||
return fmt.Errorf("failed to resolve webhook host: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user