Restrict OAuth client branding URLs to http(s)

CIMD and registration accepted any URI scheme for client_uri and
logo_uri, so allowlisted metadata could surface javascript: links on
sign-in. Validate absolute http/https at ingest and only expose those
schemes in branding.

Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
Bryan Frimin
2026-07-17 14:01:25 +02:00
parent 6da00604ed
commit e7df6f6b2a
10 changed files with 322 additions and 17 deletions

View File

@@ -40,6 +40,7 @@ import (
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/netx"
"go.probo.inc/probo/pkg/uri"
)
const (
@@ -257,6 +258,14 @@ func validateClientMetadataDocument(clientIDURL string, doc *ClientMetadataDocum
}
}
if err := validateCIMDWebURI(doc.ClientURI, "client_uri"); err != nil {
return err
}
if err := validateCIMDWebURI(doc.LogoURI, "logo_uri"); err != nil {
return err
}
authMethod := doc.TokenEndpointAuthMethod
if authMethod == "" {
authMethod = string(coredata.OAuth2ClientTokenEndpointAuthMethodNone)
@@ -310,6 +319,22 @@ func validateCIMDRedirectURI(redirectURI string) error {
return nil
}
func validateCIMDWebURI(raw, field string) error {
if raw == "" {
return nil
}
parsed, err := uri.Parse(raw)
if err != nil || !parsed.IsHTTP() {
return NewError(
ErrInvalidClient,
WithDescription("client metadata document contains invalid "+field),
)
}
return nil
}
func (f *cimdFetcher) loadCache(clientIDURL string) (*ClientMetadataDocument, bool) {
raw, ok := f.cache.Load(clientIDURL)
if !ok {