diff --git a/coderd/coderd.go b/coderd/coderd.go index 3d14ea345c..d35a22569e 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -489,16 +489,8 @@ func New(options *Options) *API { r := chi.NewRouter() // We add this middleware early, to make sure that authorization checks made // by other middleware get recorded. - //nolint:revive,staticcheck // This block will be re-enabled, not going to remove it if buildinfo.IsDev() { - // TODO: Find another solution to opt into these checks. - // If the header grows too large, it breaks `fetch()` requests. - // Temporarily disabling this until we can find a better solution. - // One idea is to include checking the request for `X-Authz-Record=true` - // header. To opt in on a per-request basis. - // Some authz calls (like filtering lists) might be able to be - // summarized better to condense the header payload. - // r.Use(httpmw.RecordAuthzChecks) + r.Use(httpmw.RecordAuthzChecks) } ctx, cancel := context.WithCancel(context.Background()) diff --git a/coderd/httpapi/authz.go b/coderd/httpapi/authz.go index f0f208d31b..78c3363dd5 100644 --- a/coderd/httpapi/authz.go +++ b/coderd/httpapi/authz.go @@ -9,6 +9,14 @@ import ( "github.com/coder/coder/v2/coderd/rbac" ) +// The x-authz-checks header can end up being >10KB in size on certain queries. +// Many HTTP clients will fail if a header or the response head as a whole is +// too long to prevent malicious responses from consuming all of the client's +// memory. I've seen reports that browsers have this limit as low as 4KB for the +// entire response head, so we limit this header to a little less than 2KB, +// ensuring there's still plenty of room for the usual smaller headers. +const maxHeaderLength = 2000 + // This is defined separately in slim builds to avoid importing the rbac // package, which is a large dependency. func SetAuthzCheckRecorderHeader(ctx context.Context, rw http.ResponseWriter) { @@ -23,6 +31,11 @@ func SetAuthzCheckRecorderHeader(ctx context.Context, rw http.ResponseWriter) { // configured on server startup for development and testing builds. // - If this header is missing from a response, make sure the response is // being written by calling `httpapi.Write`! - rw.Header().Set("x-authz-checks", rec.String()) + checks := rec.String() + if len(checks) > maxHeaderLength { + checks = checks[:maxHeaderLength] + checks += "" + } + rw.Header().Set("x-authz-checks", checks) } }