errorcoredocsbeta

Security and PII

errorcore captures runtime evidence, so its handling of sensitive data has to be explicit. This page states what is captured, what never leaves your process, and how every gap is labeled.

Encryption boundary

The SDK encrypts each error payload with AES-256-GCM in-process, using a key derived from your ERRORCORE_DEK. The envelope carries an outer HMAC that the receiver verifies before attempting decryption. The ingest API stores the encrypted envelope bytes exactly as received. Server-side project-key material remains KMS-wrapped at rest and is unwrapped only for processing in the worker.

Raw envelopes never open in the console. Event detail shows safe metadata and ends the preview with [encrypted payload hidden]. Decrypted evidence appears only on case investigation surfaces.

What is captured

Stack frames with ownership classification, local variables and bound arguments, the ordered I/O before the throw (database, HTTP, DNS, Redis, queue), request metadata, trace and span context, process and release metadata, and a completeness record describing the capture itself.

Value states

Every captured value carries exactly one state, and the console renders it literally:

StateMeaning
capturedThe value as recorded at the throw site.
redactedMatched the scrubbing policy. Rendered as the literal [REDACTED].
truncatedThe surviving prefix, plus a truncation tag.
missingNot captured. The reason is always named.
derivedComputed from other captured data, labeled as such.

The UI never fills a gap with something that looks like data.

Scrubbing

Scrubbing runs in the SDK before encryption, and the server re-checks policy after decryption. It covers frame locals and arguments, request and response bodies, headers, database bind parameters, and I/O payload previews.

Header capture uses an allowlist plus a blocklist. The blocklist matches, at minimum: authorization, cookie, set-cookie, proxy-authorization, x-api-key, x-auth-token, x-access-token, x-refresh-token, x-csrf-token, x-secret-token; compounds such as api-key, auth-token, secret-key, session-secret; and standalone password, passwd, credential. Operational headers such as idempotency-key, etag, and traceparent are preserved deliberately; the blocklist uses word boundaries so they survive.

Environment-variable capture is allowlist-only, restricted to non-sensitive operational names such as NODE_ENV, PORT, region, and pod identity; anything matching key, secret, token, password, credential, auth, or private patterns is blocked.

Deliberately dropped

These never reach errorcore storage, by design:

  • Raw environment-variable values outside the allowlist.
  • Authorization and cookie header values.
  • Captured values matching credential scrub patterns.
  • KMS and provider tokens.
  • Raw source file paths in persisted case rows: they contribute to the grouping fingerprint as a hash only.
  • The ERRORCORE_DEK itself, which never appears on the wire in any form.

SDK health metrics are also never sent; getHealth() is local observability only.

Bounds and gaps

Capture is bounded: serialization depth, array and object size, string length, payload size, and total package size all have caps, as do the payload spool and the number of frames whose locals are collected. When a bound truncates or drops something, the completeness record names the specific gap and its reason; for example, a response body dropped for exceeding the capture cap.

A partial capture that explains itself is more trustworthy than a full-looking one that does not, so completeness is shown on every case.

Your responsibilities

  • Keep ERRORCORE_API_KEY and ERRORCORE_DEK server-side. Never in browser code, never behind a public env prefix such as NEXT_PUBLIC_.
  • Tighten scrubberPolicy if your domain has PII the default patterns do not match.
  • Reduce body capture when payloads routinely carry regulated data.
  • Rotate credentials on exposure: API keys, encryption keys.

Reporting a vulnerability

A verified private vulnerability-reporting route has not yet been published. Do not put a suspected authentication, tenant-isolation, credential, cryptographic, payload, privacy, or data-integrity defect in a public issue or send it to the intended support mailbox. Never send customer payloads, credentials, cookies, tokens, decrypted values, or personal data. Publishing a verified private route is a launch blocker.

On this page