0b7d80cee0
System means "the plane itself, in-process" (router, coordinator, adapters, lease-expiry reclaim) and is unconditionally FullControl with no token gate. But it was reachable straight from the X-Orchestra-Surface HTTP header, both in authz.HTTP's token check and in main.go's own `surface` closure (which every handler actually calls to authorize an event — it re-parses the header independently of what the HTTP middleware resolved). Since no deployment configures ORCHESTRA_SYSTEM_TOKEN (no legitimate HTTP caller should ever need one), tokens[System] is always "", so the token check was skipped entirely: any LAN request with "X-Orchestra-Surface: system" got unauthenticated full control to emit any event on any task. Both the authz.HTTP middleware and main.go's `surface` closure now downgrade System to Web before doing anything else with it, so the header can never resolve to System over HTTP regardless of token config. AUDIT.md B8.
49 lines
1.9 KiB
Go
49 lines
1.9 KiB
Go
package authz
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestSurfaceCapabilities(t *testing.T) {
|
|
if Telegram.CanEmit("TaskCreated") || Ntfy.CanEmit("ApprovalRequested") {
|
|
t.Fatal("notify surface emitted an event")
|
|
}
|
|
if !TUI.CanEmit("TaskCreated") {
|
|
t.Fatal("control surface cannot emit")
|
|
}
|
|
if !MCP.CanEmit("ApprovalRequested") || MCP.CanEmit("TaskCreated") {
|
|
t.Fatal("mcp gate is wrong")
|
|
}
|
|
}
|
|
|
|
// TestSystemSurfaceDowngradedByHTTPMiddleware guards half of B8: System
|
|
// means "the plane itself, in-process" and is always FullControl with no
|
|
// token gate, since no deployment configures a token for a surface no HTTP
|
|
// caller is meant to use. HTTP() must never let a request pass through
|
|
// treated as System, or a caller declaring X-Orchestra-Surface: system gets
|
|
// an unconditional, unauthenticated bypass of the token check below it.
|
|
// (Downstream handlers must independently avoid re-deriving System from the
|
|
// raw header themselves — see cmd/orchestra/main.go's `surface` closure,
|
|
// which this package cannot test directly.)
|
|
func TestSystemSurfaceDowngradedByHTTPMiddleware(t *testing.T) {
|
|
tokens := map[Surface]string{System: "should-never-be-checked"}
|
|
h := HTTP(tokens, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
req := httptest.NewRequest(http.MethodPost, "/v1/tasks/t1/complete", nil)
|
|
req.Header.Set("X-Orchestra-Surface", "system")
|
|
rec := httptest.NewRecorder()
|
|
h.ServeHTTP(rec, req)
|
|
// System's token check is intentionally skipped by HTTP() (it downgrades
|
|
// to Web before the token comparison), so the request reaching the
|
|
// handler at all is expected here — the guard that matters is that
|
|
// nothing downstream can observe "system" as the resolved surface. This
|
|
// test documents the middleware's half of the fix; main.go's `surface`
|
|
// closure carries the other half.
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("unexpected status %d", rec.Code)
|
|
}
|
|
}
|