Tolerate trailing slash in cluster publicUrl · Entire

Tolerate trailing slash in cluster publicUrl

8fc7b1c→main·

toothbrush·3w ago·2 files·+8 added/-3 removed

hostFromPublicURL rejected any non-empty path, so a catalog entry like https://aws-us-east-2.entire.io/ (Path == "/") was dropped in clustersToRegions — silently removing clusters and risking "no regions available to mirror into" if the control plane emits trailing slashes. publicUrl is a trusted catalog field, so accept a bare "/" path; real paths/queries/fragments/userinfo are still refused. (Trail review)

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Sessions

32af87a69f30View transcript

?\ Interactive Repo Mirror Onboarding WizardClaude Code·1 step

Changes

2

102 unmodified lines

103
104
105
106
107
108
106
107
108
109
110
111
112
113
114

102 unmodified lines

// Reject anything beyond scheme://host[:port]. url.Parse demotes the
    // `host@evil.com` userinfo trick into u.User (leaving u.Host=evil.com) and
    // stashes a trailing path in u.Path, neither of which validateClusterHost
    // would otherwise see. Same belt-and-suspenders the positional <cluster-host>
    // arg gets — the host flows into clone URLs and the STS audience.
    if u.User != nil || u.Path != "" || u.RawQuery != "" || u.Fragment != "" {
    // would otherwise see. A bare "/" path is tolerated: publicUrl is a trusted
    // catalog field, and a trailing slash (https://host/) is benign — rejecting
    // it would silently drop the cluster and could leave the wizard with no
    // regions. Anything richer (a real path, query, fragment, userinfo) is still
    // refused, since the host flows into clone URLs and the STS audience.
    if u.User != nil || (u.Path != "" && u.Path != "/") || u.RawQuery != "" || u.Fragment != "" {
        return "", fmt.Errorf("public_url %q must be scheme://host[:port] only", raw)
    }
    if err := validateClusterHost(u.Host); err != nil {

Mcmd/entire/cli/repo_mirror_create_wizard.go+6/-3

66 unmodified lines

67
68
69
70
71
72
73
74

66 unmodified lines

{name: "bare host", in: "eu-west-1.entire.io", want: "eu-west-1.entire.io"},
        {name: "host with port", in: "https://localhost:8080", want: "localhost:8080"},
        {name: "trims space", in: "  https://aws-us-east-2.entire.io  ", want: "aws-us-east-2.entire.io"},
        // A trailing slash is a benign catalog shape, not a path injection.
        {name: "trailing slash", in: "https://aws-us-east-2.entire.io/", want: "aws-us-east-2.entire.io"},
        {name: "empty", in: "", wantErr: true},
        // userinfo trick rejected by validateClusterHost
        {name: "userinfo injection", in: "https://aws-us-east-2.entire.io@evil.com", wantErr: true},

Mcmd/entire/cli/repo_mirror_create_wizard_test.go+2