git-remote-entire: case-insensitive core URL comparison via shared helper · Entire
git-remote-entire: case-insensitive core URL comparison via shared helper
96c8d87·
Soph·1mo ago·4 files·+37 added/-9 removed
Core URL scheme and DNS host are case-insensitive (RFC 3986); the prior comparisons folded only the trailing slash, so a mixed-case aud or issuer would fail to match an otherwise-identical core. Extract auth.EqualCoreURL (trailing-slash- and case-insensitive) and use it for both the ENTIRE_TOKEN trust gate (coreTrusted) and context matching (formerly sameIssuer) so the two agree on core-URL identity. Safe for the trust gate: case folding only makes variants of the same DNS host match, never a different host.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
baf4d553f9bdView transcript
Changes
4
cmd
entire/cli/auth
Mcontexts.go+10/-5
Mcontexts_test.go+21
git-remote-entire
Mmain.go+4/-4
Mmain_test.go+2
104 unmodified lines
105
106
107
108
108
109
110
111
13 unmodified lines
125
126
127
128
129
130
128
129
130
131
132
133
134
135
136
137
138
31 unmodified lines
170
171
172
168
173
174
175
176
104 unmodified lines
// uniqueness.
func pickContextName(f *contexts.File, coreURL, handle string) string {
for _, c := range f.Contexts {
if sameIssuer(c.CoreURL, coreURL) && c.Handle == handle {
if EqualCoreURL(c.CoreURL, coreURL) && c.Handle == handle {
return c.Name
}
}
}
}
// sameIssuer compares two core URLs ignoring a trailing slash.
func sameIssuer(a, b string) bool {
return strings.TrimRight(a, "/") == strings.TrimRight(b, "/")
}
// EqualCoreURL reports whether two core URLs denote the same origin, ignoring
// a trailing slash and host case. URL scheme and DNS host are case-insensitive
// (RFC 3986 §3.1, §3.2.2); core URLs are validated bare origins (no path), so a
// whole-string case fold is equivalent to folding only scheme+host here. Shared
// by context matching and the ENTIRE_TOKEN trust gate so both agree on what
// counts as "the same core".
func EqualCoreURL(a, b string) bool {
return strings.EqualFold(strings.TrimRight(a, "/"), strings.TrimRight(b, "/"))
}
// MigrateLegacyLoginContext bridges users who logged in before the
// issuer alone would skip a legacy bob@core just because alice@core (e.g.
// from another CLI) already exists, leaving Bob without a context.
for _, c := range f.Contexts {
if sameIssuer(c.CoreURL, claims.Issuer) && c.Handle == handle {
if EqualCoreURL(c.CoreURL, claims.Issuer) && c.Handle == handle {
return false, nil
}
}
}
Mcmd/entire/cli/auth/contexts.go+10/-5
23 unmodified lines
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
23 unmodified lines
return header + "." + payload + "." + enc.EncodeToString([]byte("sig")) }
func TestEqualCoreURL(t *testing.T) { t.Parallel() tests := []struct { a, b string want bool }{ {"https://core.us.entire.io", "https://core.us.entire.io", true}, {"https://core.us.entire.io/", "https://core.us.entire.io", true}, {"https://Core.US.Entire.IO", "https://core.us.entire.io", true}, {"HTTPS://core.us.entire.io", "https://core.us.entire.io", true}, {"https://core.us.entire.io", "https://core.eu.entire.io", false}, {"", "https://core.us.entire.io", false}, {"", "", true}, } for _, tc := range tests { if got := EqualCoreURL(tc.a, tc.b); got != tc.want { t.Errorf("EqualCoreURL(%q, %q) = %v, want %v", tc.a, tc.b, got, tc.want) } } }
func TestRecordLoginContext_WritesContextAndToken(t *testing.T) { // Sets ENTIRE_CONFIG_DIR and swaps the keyring backend — process-global // state, so this test cannot run in parallel. }
Mcmd/entire/cli/auth/contexts_test.go+21
200 unmodified lines
201
202
203
204
205
204
205
206
207
207
208
209
209
210
211
212
200 unmodified lines
// coreTrusted reports whether coreURL is in the cluster's advertised core
// set, comparing on trailing-slash-insensitive equality to match how core
// URLs are compared elsewhere (contexts.ContextsForIssuer, auth.sameIssuer).
// set, comparing via auth.EqualCoreURL (trailing-slash- and host-case-
// insensitive) so the trust gate agrees with how core URLs are matched
// during context resolution.
func coreTrusted(coreURL string, trusted []string) bool {
want := strings.TrimRight(coreURL, "/")
for _, t := range trusted {
if strings.TrimRight(t, "/") == want {
if auth.EqualCoreURL(coreURL, t) {
return true
}
}
}
}
Mcmd/git-remote-entire/main.go+4/-4
50 unmodified lines
51 52 53 54 55 56 57 58
50 unmodified lines
{"exact match", "https://core.us.entire.io", true}, {"trailing slash on candidate", "https://core.us.entire.io/", true}, {"trailing slash on trusted entry", "https://core.eu.entire.io", true}, {"mixed-case host matches", "https://Core.US.Entire.IO", true}, {"mixed-case scheme matches", "HTTPS://core.us.entire.io", true}, {"not in set", "https://attacker.example.com", false}, {"empty against set", "", false}, } }`