Pulp EngineDocument Rendering
Get started
Release v0.85.1

Release v0.85.1 — Security & maintenance patch (2026-10-09)

Production dependencies built up 1 critical and 69 high advisories in the four months after v0.85.0. This patch clears all of them, restores scheduled email delivery in the Docker image, repairs the HA reference stack, and fixes documentation that still called the SDKs unpublished. No API, template-format, or configuration changes. Upgrading is a straight image swap.

Upgrade

Pull ghcr.io/troycoderboy/pulp-engine:v0.85.1 (and the -worker / -controller images if you run RENDER_MODE=container or socket). No migrations, env-var changes, or template changes are required.

If you run the HA reference stack (docker-compose.ha.yml), pull the updated compose file too: its MinIO images no longer exist on Docker Hub (see below).

Security

pnpm audit --prod went from 137 findings (1 critical, 69 high, 57 moderate, 10 low) to 0 unignored. The fixes that matter at runtime:

Area Package → version What it fixes
API fastify → 5.12.5 Auth bypass via malformed URLs reaching not-found handlers; schema-validation bypasses
API @fastify/static → 10.1.5 Route-guard bypass via path traversal (static assets, bundled editor)
API @fastify/busboy → 3.2.2, find-my-way → 9.7, undici → 8.11.2, fast-uri → 3.1.8 Multipart DoS, router DoS, HTTP-client TLS/DoS issues, URI host confusion
PDF renderer Puppeteer → 25.12 Removes extract-zip, ip-address and basic-ftp from the dependency tree
Editor prosemirror-view → 1.42.3 XSS in paste handling
Website Astro → 7.3.7 Remote code execution in image optimization (build time only — the site is static)

Two advisories are recorded as not reachable rather than fixed. Both are listed in pnpm.auditConfig.ignoreGhsas, so the audit gate still fails on anything new:

  • sprintf-js GHSA-hp3w-g68c-fv3c (moderate). There is no fixed version. It is pulled in by the SQL Server driver (tedious), which only ever passes literal format strings, so attacker input never reaches a precision specifier.
  • @tiptap/core GHSA-cp6q-959q-f8rh (moderate). The editor converts rich-text content to Tiptap documents by building attributes from a fixed set (color, href), so an own __proto__ key cannot reach mergeAttributes. The fix exists only in Tiptap 3; that migration is planned for a later release.

Fixed

  • Scheduled email delivery works in the Docker image. The API loads nodemailer only when an email target fires, but the package was never declared as a production dependency. The published image therefore did not contain it, and every schedule email target failed with ERR_MODULE_NOT_FOUND. This has been broken in every image since scheduling shipped; unit tests replaced nodemailer with a mock, so they never noticed. If you use schedule email targets, check schedule executions and the schedule dead-letter queue (GET /admin/schedule-dlq) for deliveries that failed this way. A new contract test now fails the build if shipped API code imports a package that is not a production dependency.
  • HA reference stack boots again. minio/minio and minio/mc pulls have been denied since September 2026, so docker-compose.ha.yml and docker-compose.benchmark.yml failed at startup. Both now use cgr.dev/chainguard/minio:latest-dev (MinIO rebuilt from source; includes mc), which also runs the bucket-setup job. The health check uses wget instead of curl.
  • PDF page settling under Puppeteer 25. Puppeteer 25 no longer accepts networkidle0 when setting page content. The renderer now loads the page and then waits for 500 ms with no network activity, inside the same 30 s budget. Render behaviour and the dispatcher watchdog arithmetic are unchanged.

Changed

  • openapi.json nullable fields. @fastify/swagger 9.9 writes nullable fields as OpenAPI 3.0 nullable: true instead of anyOf with a null type. The spec is otherwise identical (81 operations) and the generated TypeScript SDK types do not change. Client generators that target OpenAPI 3.0 handle the new form natively.
  • Published packages are documented as published. @pulp-engine/sdk, @pulp-engine/template-model and @pulp-engine/cli are on npm and pulp-engine is on PyPI. README, LICENSING.md, the SDK READMEs, the SDK guide and the website said they were still pending.

Validation

CI-verified — the release.yml check-ci gate requires a green push-CI run on the release commit (ci, test-file-mode, test-sqlserver, test-e2e, test-e2e-auth, Docker build + smoke, Windows installer, evaluation bundle).

Locally verified (Windows 11 + Docker Desktop):

  • pnpm audit --prod --audit-level=moderate passes (2 moderate, both ignored as above).
  • pnpm build, pnpm typecheck (including astro check: 0 errors) and pnpm lint pass.
  • Non-API test suites pass. The only failures under the parallel full run were Windows timing flakes that pass when re-run alone: one pptx-renderer chart test, and the editor login-identity test, which flakes the same way on v0.85.0.
  • API suites covering the upgraded packages pass: static serving, asset upload and access modes, embed/form assets, OpenAPI auth coverage, metrics, security hardening, error contract, OTel spans and config validation (11 files, 243 passed, 1 skipped).
  • pnpm extract-openapi --check passes; the only spec change is the nullable representation above.
  • THIRD-PARTY-NOTICES.md was regenerated on Linux (node:22 container) from a clean checkout; no disallowed licenses.
  • The MinIO replacement was booted on its own: health check green, bucket created, setup job exits 0.

Not verified locally

  • The full API suite (about 70 minutes serial on Windows) runs in CI only.
  • SQL Server and the end-to-end Playwright suites run in CI only.
  • The HA nightly checks run in GitHub Actions after merge; a passing nightly is the evidence that the HA stack is repaired end to end.