GitHub
11/08/2026, 3:39 PMr.Body with no limit. That left two problems:
• One huge body to any of those endpoints could run osctrl-api out of memory.
• Query text had no length limit. Any user with query rights could submit, say, a 50 MB SQL query. It would be stored and sent to every targeted node on each distributed read until the nodes answered.
What changes
• handlerAuthCheck wraps every authenticated request body in http.MaxBytesReader with a default cap of 8 MiB, under both JWT and auth=none.
• Handlers that set a smaller cap keep it.
• Multipart requests are skipped: the extension upload streams its file and enforces its own limit.
• Why 8 MiB rather than 1 MiB: the environment config PATCH carries the whole osquery configuration, packs included, which can legitimately be several megabytes. An outer cap can't be raised by a handler.
• New queries.MaxQueryLength (64 KiB). It is enforced when running an on-demand query (POST /api/v1/queries/{env}) and when creating or updating a saved query, with 400 query too long. MCP and the CLI's API mode go through the same handlers.
Security and operational impact
• Bounds per-request memory on osctrl-api, and stops oversized queries being stored and sent to the fleet.
• Handlers without their own cap report an oversized body as their usual parse error (400, or 500 on some), not 413. The request is refused either way.
• The CLI's direct-database mode is trusted operator tooling and is not limited.
• No schema or API shape changes, and the OpenAPI output is unchanged.
Validation
• `TestHandlerAuthCheckCapsBodies`: a body at the cap reads fully, one byte over fails with *http.MaxBytesError, and a multipart body over the cap is left to its handler.
• `TestQueryTextLengthLimit`: running a query, creating a saved query and updating a saved query all answer 400 query too long past 64 KiB, and no query is stored. A normal saved query is still created.
• Both failed before the change.
• go test ./... passes (uncached) and make openapi-check is clean.
jmpsec/osctrlGitHub
11/08/2026, 3:56 PM