fix(coderd): harden Azure identity certificate fetch (#25274)

Security improvements:
- Restrict cert fetches to a host+port allowlist (Microsoft and DigiCert
on 80/443).
- Route requests through a dedicated `http.Client` that resolves the
host once and dials the validated IP directly, preventing DNS rebinding.
- Reject loopback, private (RFC 1918 / IPv6 ULA), link-local, multicast,
unspecified, CGNAT, benchmarking, and IPv4-mapped IPv6 addresses.
- Cap the certificate response body at 1 MiB.
- Log the underlying error via slog and return a generic detail to the
caller to prevent information disclosure.
This commit is contained in:
Jakub Domeracki
2026-05-13 12:51:44 +02:00
committed by GitHub
parent 9400eaa957
commit 57b11d405f
4 changed files with 297 additions and 11 deletions
+10 -1
View File
@@ -8,6 +8,7 @@ import (
"github.com/mitchellh/mapstructure"
"cdr.dev/slog/v3"
"github.com/coder/coder/v2/coderd/awsidentity"
"github.com/coder/coder/v2/coderd/azureidentity"
"github.com/coder/coder/v2/coderd/database/dbauthz"
@@ -38,9 +39,17 @@ func (api *API) postWorkspaceAuthAzureInstanceIdentity(rw http.ResponseWriter, r
VerifyOptions: api.AzureCertificates,
})
if err != nil {
// Log the full error for operators but return only a
// generic message to the caller. Errors from the
// certificate fetch path may contain fragments of
// internal HTTP responses, so exposing them would be
// an information disclosure risk.
api.Logger.Warn(ctx, "azure identity validation failed",
slog.Error(err),
)
httpapi.Write(ctx, rw, http.StatusUnauthorized, codersdk.Response{
Message: "Invalid Azure identity.",
Detail: err.Error(),
Detail: "Signature verification failed.",
})
return
}