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:
| State | Meaning |
|---|---|
captured | The value as recorded at the throw site. |
redacted | Matched the scrubbing policy. Rendered as the literal [REDACTED]. |
truncated | The surviving prefix, plus a truncation tag. |
missing | Not captured. The reason is always named. |
derived | Computed 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_DEKitself, 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_KEYandERRORCORE_DEKserver-side. Never in browser code, never behind a public env prefix such asNEXT_PUBLIC_. - Tighten
scrubberPolicyif 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.