Primate 0.45.1: bounded bodies, safer validation and response hardening

Primate 0.45.1 is a security patch for the 0.45 line. It bounds buffered request bodies, fixes email-validation backtracking, prevents a same-origin redirect bypass, and cleans up streaming responses discarded by HEAD requests. We recommend updating applications on 0.45 and reviewing the new body limits.

If you're new to Primate, we recommend reading the quickstart page to get started.

Bounded bodies

Primate's request.body convenience readers count received bytes before decoding or schema validation. The default maximum is 1 MiB for JSON, URL-encoded form and text, and 16 MiB total for multipart and binary bodies. Multipart accounting includes boundaries, fields and file contents. The limit works without Content-Length; an oversized declared length is rejected early. Overflow cancels reading and responds with HTTP 413 Payload Too Large, without waiting for the client to finish uploading.

Upgrade action: applications accepting larger requests must explicitly raise http.body.limit or http.body.uploadLimit in their configuration, or use route.with({ limit: bytes }, handler) for an individual handler. Limits are positive safe integer byte counts. For example, a route accepting binary uploads up to 32 MiB can declare:

import route from "primate/route";

export default route({
  post: route.with({
    contentType: "application/octet-stream",
    limit: 32 * 1024 * 1024,
  }, async request => {
    const upload = await request.body.blob();
    return { bytes: upload.size };
  }),
});

The client must send Content-Type: application/octet-stream, matching the route's declaration and the blob() reader. These are buffered readers, not a streaming upload API. A higher limit permits larger memory allocations. Direct reads through request.original and forwarding its stream bypass these limits. Per-file/part limits, concurrent-request limits, timeouts and upstream transport/proxy limits are separate controls; this patch does not claim to eliminate every denial-of-service risk.

Safer validation

Pema's email validator no longer performs quadratic backtracking on long invalid dot sequences, which could block a server's event loop during unauthenticated validation. A request-body cap alone is not a substitute for this fix. The accepted email formats and custom messages are unchanged.

SMTP/DNS email byte-length policy and IDNA changes are separate work and are not part of this release. No email-length migration is required here.

Response hardening

Same-origin redirects now normalize leading slashes after URL dot-segment resolution. This prevents a checked same-origin target from being emitted as a protocol-relative external location, including relative redirects from request paths that start with repeated slashes. The fix covers ordinary Location and enhanced-navigation Primate-Redirect headers. Explicit allowExternal behavior is unchanged.

HEAD responses cancel discarded GET response bodies, including SSE streams and native responses passed to response.abort(). This releases stream-owned timers and subscriptions instead of leaking resources on repeated HEAD requests. Status and headers are preserved; cancellation is not awaited and failed cancellation does not turn HEAD into an error. Applications remain responsible for body readers they have already locked.

This maintenance line also includes the Go module proxy discovery correction and API documentation corrections merged after 0.45.0. It does not change the Go/Python/Ruby/Kotlin SDK compatibility line or require new SDK publications.

Acknowledgements

The Primate team would like to thank theskillwithin for reporting these security issues.

Update dependencies and lockfiles

The npm patch versions are:

Package Fixed version
primate 0.45.1
@primate/core 0.14.1
pema 0.14.1

Update your project lockfile and reinstall dependencies, then inspect the resolved versions. An existing lockfile can retain an older Core or Pema even when a compatible manifest range allows the fixed version. A top-level manifest edit or an install that simply reuses the old lockfile is not enough. Do not delete the lockfile wholesale; review and commit the targeted update.

Flog users can review and apply a targeted update of their direct dependencies.

If your manifest pins an older exact version or excludes these patches, first update those declarations to the fixed maintenance versions above. The commands below respect your configured version ranges; they are not a request to jump to another release line.

flog upgrade primate @primate/core pema --dry-run --json
flog upgrade primate @primate/core pema --yes
flog install

The command names all three packages, but only declarations present in your project are direct dependencies. Review flog.lock and check the installed dependency graph, including transitive Core/Pema copies: this line should resolve primate to 0.45.1 or a later compatible patch, and Core/Pema to 0.14.1 or later compatible patches. Updating Primate's dependency chain does not guarantee that other installed packages no longer retain an older copy. With another package manager, use its targeted update and dependency-inspection commands and commit its updated lockfile as well.

This is a same-line patch, not an upgrade to 0.46. Review the body-limit action above, test affected request/upload routes, and deploy the rebuilt application after verifying the installed versions.