fstests: check a root starting with // can't move the remote to another host GHSA-xqmq-v4wj-rw5m CVE-PENDING

Add an integration test which starts a listener on localhost, makes
the remote with roots naming that listener and checks that nothing
connects to it. The listener replies with junk so a backend which does
connect fails at once rather than retrying a closed connection.
This commit is contained in:
Nick Craig-Wood committed 2026-10-08 22:49:33 +01:00
1 parent 28562c8a79
commit f33fa3872f
1 file changed
+45
+45
View File
@@ -597,6 +597,51 @@ func Run(t *testing.T, opt *Opt) {
}
})
// TestFsRootCannotChangeHost tests that a root beginning with //
// is treated as a path and can't move the remote to a host of the
// attacker's choosing.
//
// A root beginning with // is a network-path reference under the
// URL standard so a backend which resolves its root as a URL
// reference against a configured URL could send requests, and
// whatever credentials go with them, to the host named in the root.
t.Run("FsRootCannotChangeHost", func(t *testing.T) {
skipIfNotOk(t)
if !strings.HasSuffix(remoteName, ":") {
t.Skip("root of a path based remote can't be a network-path reference")
}
ln, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
defer func() { _ = ln.Close() }()
var connections atomic.Int32
go func() {
for {
conn, err := ln.Accept()
if err != nil {
return
}
connections.Add(1)
// Reply with junk so the client fails at once rather than retrying a closed connection
_, _ = conn.Write([]byte("\x00\xff\x00\xff junk\n"))
_ = conn.Close()
}
}()
host := ln.Addr().String()
for _, root := range []string{
"//" + host + "/",
"//" + host + "/" + subRemoteLeaf + "/",
"//user:pass@" + host + "/",
} {
remote := remoteName + root
f, err := fs.NewFs(context.Background(), remote)
if err == nil {
// Not all backends contact the remote in NewFs
_, _ = f.List(context.Background(), "")
}
assert.Equal(t, int32(0), connections.Load(), "remote %q connected to the host named in its root", remote)
}
})
// TestFsRmdirEmpty tests deleting an empty directory
t.Run("FsRmdirEmpty", func(t *testing.T) {
skipIfNotOk(t)