Skip to content

[finding] AuthzStoreUnavailableError brand doc claims structuredClone survival, which is false for an Error #14006

Description

@claude

Found while implementing #13905, which followed this module as its brand precedent. Recorded for triage; no severity asserted.

The shape

packages/core/src/security/authz-store-unavailable.ts documents its brand as a string-keyed own property chosen so that it survives structuredClone:

A string-keyed own property (not a Symbol.for registry key) so it survives
structuredClone, and so a duplicated copy of this module still brands identically.

The second half is correct and is the reason the choice is right. The first half is not true for an Error.

Measured

Node 22.22.2, on the box this repo builds on:

const e = new Error('x'); e.__brand = true; e.code = 'C';
const c = structuredClone(e);
// c.__brand === undefined   c.code === undefined   c.name === 'Error'   c.message === 'x'

The structured-clone algorithm gives Error objects a dedicated serialization that carries name, message, stack and cause and drops every other own property — so both the brand and the ADR-0112 code are lost. For a plain object the doc claim would hold; for an Error subclass it does not.

Why it is worth recording rather than shrugging at

Nothing is broken today: isAuthzStoreUnavailableError is used on in-process rethrow paths (rethrowAuthzStoreUnavailable), where no cloning happens, so the predicate answers correctly everywhere it is actually called.

The cost is in propagation. This module is the governed precedent an author copies when they need a branded error, and the claim travels with it — the #13905 discriminator was written with that sentence copied verbatim and only lost it because the claim was measured before being repeated. A stated rationale that is false is also a trap in the other direction: it reads as a licence to send one of these across a worker or postMessage boundary and branch on the brand at the far end, which would silently answer false and fail open.

Suggested shape of the repair

Keep the property, keep the reasoning that earns it (a duplicated copy of the module still brands identically, which instanceof does not), and either drop the structuredClone clause or state the measured behaviour. No runtime change.

Related: #13905 (the module that would have inherited the claim; its own doc now states the measured behaviour instead).


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions