diff --git a/workspace-server/internal/handlers/registry.go b/workspace-server/internal/handlers/registry.go index 299436d31..f17603cb7 100644 --- a/workspace-server/internal/handlers/registry.go +++ b/workspace-server/internal/handlers/registry.go @@ -309,6 +309,8 @@ func validateAgentURL(rawURL string) error { // (covers prod `*.moleculesai.app` and staging `*.staging.moleculesai.app`) and // is overridable via MOLECULE_APP_DOMAIN for other deployments. func isPlatformTunnelHostname(h string) bool { + // DNS is case-insensitive and FQDN-form hostnames may carry a trailing dot. + h = strings.ToLower(strings.TrimSuffix(h, ".")) if !strings.HasPrefix(h, "ws-") { return false } @@ -316,6 +318,7 @@ func isPlatformTunnelHostname(h string) bool { if domain == "" { domain = "moleculesai.app" } + domain = strings.ToLower(strings.TrimSuffix(domain, ".")) return strings.HasSuffix(h, "."+domain) } diff --git a/workspace-server/internal/handlers/registry_test.go b/workspace-server/internal/handlers/registry_test.go index 44d7a0127..949b70147 100644 --- a/workspace-server/internal/handlers/registry_test.go +++ b/workspace-server/internal/handlers/registry_test.go @@ -895,9 +895,13 @@ func TestValidateAgentURL_PendingPlatformTunnel(t *testing.T) { }{ {"ws-abc123.moleculesai.app", true}, {"ws-abc123.staging.moleculesai.app", true}, - {"ws-abc123.evil.com", false}, // not under the platform domain - {"api.moleculesai.app", false}, // no ws- prefix - {"ws-x.fakemoleculesai.app", false}, // lookalike domain, not a subdomain + {"WS-ABC123.MOLECULESAI.APP", true}, // case-insensitive DNS + {"ws-abc123.moleculesai.app.", true}, // FQDN trailing dot + {"WS-ABC123.STAGING.MOLECULESAI.APP.", true}, // both case + trailing dot + {"ws-abc123.evil.com", false}, // not under the platform domain + {"api.moleculesai.app", false}, // no ws- prefix + {"ws-x.fakemoleculesai.app", false}, // lookalike domain, not a subdomain + {"ws-abc123moleculesai.app", false}, // missing dot before platform domain } { if got := isPlatformTunnelHostname(tc.h); got != tc.want { t.Errorf("isPlatformTunnelHostname(%q)=%v want %v", tc.h, got, tc.want)