# Spec 378 Gotenberg Security Controls Date: 2026-06-14 Decision: Gotenberg 8 Chromium is approved with controls as an internal production PDF rendering service for report-style documents. These are required future implementation controls. This artifact does not add runtime config and does not claim that Gotenberg is already deployed in the repo. ## Required Runtime Boundary - Gotenberg runs as a separate internal Docker service. - The Laravel app and queue containers do not install or execute Node, Puppeteer, Chrome, Chromium, or a browser binary for production PDF rendering. - Laravel accesses the service only through a narrow `PdfRenderingGateway` / `PdfRendererClient`. - The gateway exposes only server-generated HTML-to-PDF rendering required by report generators. - No user-provided URL rendering is allowed in Spec 378 v1. - No public port is exposed for the renderer in Sail or Dokploy. - The service is reachable only over the internal Docker/Dokploy network. ## Required Image And Deployment Controls - Use a pinned Gotenberg 8 Chromium image version or immutable digest; never `latest`. - Prefer the Chromium-only Gotenberg 8 image variant for v1 unless office conversion is explicitly approved later. - Record the exact image tag/digest in the implementation PR. - Add a health check using Gotenberg `/health`. - Configure startup/readiness behavior so unavailable renderer state fails generation before artifact exposure. - Configure resource limits appropriate for PDF generation workers. - Configure request timeout (`API_TIMEOUT`) and Chromium startup timeout (`CHROMIUM_START_TIMEOUT`) explicitly. - Configure multipart request size limit (`API_BODY_LIMIT`) explicitly. - Configure Chromium queue/concurrency limits (`CHROMIUM_MAX_QUEUE_SIZE`, `CHROMIUM_MAX_CONCURRENCY`) explicitly. - Disable unused webhook behavior unless a future spec explicitly approves it. - Disable or do not use `downloadFrom` in v1. ## Required Request Controls - Send HTML as a server-generated `index.html` multipart payload. - Send only local bundled assets alongside the HTML payload. - Reference assets by relative filename only. - Do not send signed URLs inside HTML. - Do not send access tokens, refresh tokens, client secrets, provider credentials, raw provider payloads, SQL errors, stack traces, serialized job context, or internal MSP-only notes inside HTML. - Do not render arbitrary operator-provided HTML. - Do not render arbitrary user-provided remote URLs. - Apply max HTML payload size, max asset size, and max PDF output size in the Laravel gateway before calling Gotenberg. - Add a correlation id / OperationRun id to request metadata, using the configured Gotenberg correlation header. ## Required Network And File-Access Controls - Keep Gotenberg internal-only with no public listener. - No direct user-provided URL rendering in v1. - Deny or tightly restrict outbound URL access. - For Spec 378, default to no external outbound fetches: use bundled local assets only. - Set Chromium outbound restrictions to reject public and private external HTTP destinations unless a later approved asset host allow-list is introduced. - Do not enable file access beyond Gotenberg's per-request working directory defaults. - Keep Chromium file access from files disabled. - Do not mount application storage, secrets, `.env`, or host paths into the Gotenberg container. - If custom fonts are required later, use a dedicated reviewed font image or readonly font mount with no secrets. ## Required Error And Audit Controls - Renderer unavailable must map to OperationRun failed/blocked with safe reason. - Renderer timeout must map to OperationRun failed/blocked with safe reason. - Renderer 400/503 responses must map to structured internal error classes. - Do not expose raw renderer errors to customers. - No ghost report: failed generation must not expose a ready artifact, stale download URL, or partially written PDF. - Renderer logs must not contain secrets because request HTML and metadata must be pre-sanitized. - Audit generation attempts and successful downloads with safe metadata only. - Log correlation id, source review/pack id, operation run id, profile, format, status, and safe renderer outcome. ## Required Testing And Validation Controls - Unit coverage for renderer client request building and size-limit rejection. - Feature coverage for renderer unavailable, timeout, invalid payload, and successful artifact response mapping. - Feature coverage proving no ready artifact is exposed on renderer/storage failure. - Feature coverage proving denied generation never calls the renderer. - Browser/content smoke only after runtime service and generation flow are implemented. - Deployment validation must include health check behavior and queue worker failure handling. ## Explicit Non-Approval Gotenberg is approved as shared internal PDF rendering infrastructure for report-style documents. This approval does not approve legal invoice generation, German B2B e-invoicing, XRechnung, ZUGFeRD/Factur-X, GoBD archival, tax calculation, invoice numbering, or billing compliance. ## Source Notes - Gotenberg supports Docker and Docker Compose service use, with other services able to reach it on the compose network. - Gotenberg exposes a Chromium HTML-to-PDF route accepting `index.html` plus optional assets. - Gotenberg exposes `/health` for liveness/monitoring. - Gotenberg has timeout, body limit, correlation id, Chromium concurrency, queue, file access, and outbound URL filtering settings that must be set deliberately.