R-1126: the gate publishes the container it checked, by id (TOCTOU from the commit's security review)
gates / gates (push) Successful in 42s
gates / gates (push) Successful in 42s
web.SyncFileBrowserMounts can re-create FileBrowser between the check and the connect; a connect by name would publish the new, unchecked container. The run is now "<id> <StartedAt>" and the connect targets that id. TestFileBrowserGate_ConnectsTheCheckedContainerById, red-proved. Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -296,3 +296,24 @@ func TestFileBrowserGate_PublishedOnlyAfterTheCheck(t *testing.T) {
|
||||
t.Fatalf("a checked restart did more: %v", events)
|
||||
}
|
||||
}
|
||||
|
||||
// R-1126 TOCTOU: the gate connects the container whose run it checked, by ID — so a FileBrowser re-created between the
|
||||
// check and the connect (web.SyncFileBrowserMounts runs outside infraMu) is never the one published.
|
||||
// RED-PROOF (2026-10-17): connecting by the name „filebrowser" fails this test.
|
||||
func TestFileBrowserGate_ConnectsTheCheckedContainerById(t *testing.T) {
|
||||
fb := &fakeFB{password: "admin"}
|
||||
srv := httptest.NewServer(fb.handler())
|
||||
defer srv.Close()
|
||||
m, _, _ := fbManager(t, srv.URL)
|
||||
m.fbStarted = func() string { return "3f2a9c 2026-10-17T11:20:00Z" }
|
||||
var connected []string
|
||||
m.fbNetOnFn = func(c, n string) bool { return false }
|
||||
m.fbNetConnectFn = func(c, n string) error {
|
||||
connected = append(connected, c+"@"+n)
|
||||
return nil
|
||||
}
|
||||
m.fileBrowserGateLocked()
|
||||
if len(connected) != 2 || connected[1] != "3f2a9c@traefik-public" {
|
||||
t.Fatalf("the checked container must be published by its id, got %v", connected)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user