The event-log page renders stored bodies untruncated, so buffered rendering can hold ~25 MB per request #135
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found in the independent review of #131. Not milestoned 1.0.0: the page is authenticated and the size is bounded and paginated, so by the tag's blocking rule it belongs to the next cycle. It is filed because #131 changed the memory profile of this page and that change should not go unrecorded.
templates/source_logs.html:39renders{{.Body}}untruncated. WithpaginationPerPage = 25(internal/handlers/handlers.go:31) and the 1 MB ingest cap (internal/handlers/webhook.go:17), one page can carry ~25 MB of raw bodies — before HTML escaping, which inflates adversarial payloads several-fold (html/templateescapes+to+and similar).Before #131 this streamed to the socket, so the peak was small. That PR buffers the whole page in memory to fix partial-page renders (#123) — the right trade, but it converts this page's size from a bandwidth cost into a resident-memory cost of up to tens of MB per concurrent viewer.
REPO_POLICIES.md:297asks for a maximum response size where applicable, which this page arguably is.Definition of done
Implementation requirements
next, PR based onnext, single commit, title ending(closes #N).TODO.md(see #112).make checkplus the Docker lint path with the cache defeated (#119).Plan: bound the body in the query layer, not the template.
loadEventsWithDeliverieswill stop loading[]database.Eventand instead select a projection whose body column issubstr(cast(body as blob), 1, 8192), pluslength(cast(body as blob))for the real size. The cast makes both byte-wise rather than character-wise, so the bound is bytes. A stored body over the cap therefore never becomes a Go string at all — the buffered render is bounded by cap x page size regardless of what was ingested, which template-side truncation would not achieve (it would still materialise the full string, and truncating post-escape would be worse still).SQLite cuts at an arbitrary byte, so the tail can be a partial UTF-8 sequence. A helper walks back at most
utf8.UTFMaxbytes to the lastutf8.RuneStartbyte and drops that sequence ifutf8.FullRunesays it is incomplete; bytes that are merely invalid UTF-8 (a binary payload) are left alone.Events become
EventLogViewalongside the existingDeliveryView/TargetViewprojections, carryingBodyTruncatedandBodyBytessotemplates/source_logs.htmlcan show a visible marker with the real byte count.Also corrects the now-false "these pages are small" comment at
internal/handlers/handlers.go:232.