fix(config): reject auth-source urls the resolver cannot query

The url check only looked for an http:// or https:// prefix. Several
shapes passed it and then left the source dead at login time: no host
("https://"), a bad port, surrounding whitespace (sent as %20 and
answered 404), and any query or fragment. The resolver appends
"?username=…&serverId=…" to the url as a string, so an existing query
swallows those parameters and a fragment hides them from the request
entirely. Each loaded green, and every login from that source failed.

The url is now parsed and must be http or https with a host, no query,
no fragment and no surrounding whitespace. Load and LoadNano share the
check. The shipped LittleSkin default and plain http:// endpoints, such
as a same-host root on loopback, still load.

The new test feeds each rejected shape to LoadNano. Against the previous
prefix check, six of the seven load; only ftp:// was refused.
This commit is contained in:
flyemoji committed 2026-09-22 13:23:02 +09:00
1 parent 3338d6f0fe
commit 2c74080b78
2 files changed
+51 -5

No files matched your search

+23
View File
@@ -331,6 +331,29 @@ url = "bare.example.net/hasJoined"
}
}
// TestLoadRejectsUnqueryableAuthSourceURL covers the URL shapes that carry a scheme yet can
// never be queried: the resolver appends the query string to the URL verbatim, so each of
// these would load green and leave a source that silently validates nobody.
func TestLoadRejectsUnqueryableAuthSourceURL(t *testing.T) {
for _, u := range []string{
"ftp://a.example.net/hasJoined",
"https://",
"https://a.example.net/hasJoined?token=x",
"https://a.example.net/hasJoined?",
"https://a.example.net/hasJoined#x",
"https://a.example.net/hasJoined ",
"https://a.example.net:bad/hasJoined",
} {
_, err := config.LoadNano(writeTOML(t, "[[auth_source]]\ntag = \"a\"\nprefix = \"AA\"\nurl = \""+u+"\"\n"))
if err == nil {
t.Errorf("url %q loaded; it can never be queried", u)
}
}
if _, err := config.LoadNano(writeTOML(t, "[[auth_source]]\ntag = \"a\"\nprefix = \"AA\"\nurl = \"http://127.0.0.1:8080/hasJoined\"\n")); err != nil {
t.Errorf("a plain loopback endpoint must load: %v", err)
}
}
// TestLoadNanoAcceptsMinimalConfig is the linchpin of the Felis-nano fold: a nano host has no
// Postgres and no FQDN, so LoadNano must accept a felis.toml carrying ONLY [[auth_source]] —
// the control-plane requirements (database.url, root_domain) that full Load enforces are