Skip to content

observation: guest and previewMode boots write an @anon metadata seed — benign only if /meta/* is unfiltered on those deployments, which is reasoned not measured #5828

Description

@claude

Split out of #5746 (closed latent-not-live) as the one reading that card measured but could not decide. Filed unassigned, deliberately unlabelled — this needs triage first-touch, and the deciding question is server-side, outside what the domain:ui seat can measure.

The reading

#5746 measured both of its named windows SHUT: on a real apps/console session the metadata seed is never written under the @anon principal, because ConsoleShell's #4042 session gate holds MetadataProvider from mounting until getSession() has already written TokenStorage (true for bearer and cookie-only sign-in — better-auth v1.6.28 returns session.token either way).

Two boots outside those windows do write @anon:

  • a guest boot — ConditionalAuthWrapper with enabled={false}
  • previewMode

both writing objectui:metadata:app:@none:@anon.

Why this is not obviously a defect, and not obviously safe

The argument that these are harmless is that ConditionalAuthWrapper selects those branches only when discovery reports an auth stub / handlerReady:false, or the deployment is a marketplace preview — i.e. precisely when the server is not filtering /meta/* per user, so the cached list is not a permission-filtered artifact and there is no cross-principal disclosure to make.

⚠️That argument is REASONED, not measured.#5746's dev flagged it as such rather than presenting it as a result, which is why it is being carried here instead of being closed with the parent card. Confirming or refuting it means establishing what the server actually serves on /meta/* for a stub-auth or marketplace-preview deployment — a question this repo cannot answer from the client side.

apps/console never takes either branch, so nothing shipped in the console is implicated. The exposure, if any, is in stub/preview deployments.

What #5746 established that bears on this

The parent card's most load-bearing finding is a correction: #5744's wholesale drop does not cover the seed read. React runs child effects before parent effects, so MetadataProvider's seed read (a child effect, newly mounted in the commit where isLoading flips) precedes AuthProvider's purgePreviousUserClientState (a parent effect). The principal-scoped key from #5198 is the sole protection on that boot — measured, not argued: with TokenStorage empty on an authenticated session, a second user booting in the same tab HIT the first user's key and rendered hr-secret.

So a @anon write is only benign for as long as the thing being cached is not permission-filtered. That is exactly the property this card needs someone to establish for the two synthetic-identity branches.

An asset that exists and is not merged

#5746's harness renders the real console mount path — real AuthProvider, real ConnectedShell session gate, real MetadataProvider, with only the two servers doubled, and nothing writing objectui:metadata:* by hand (so it cannot agree with a key format the provider does not produce). It is the instrument that produced every reading above, including the S4/S5 writes this card is about.

It lives unmerged on claude/issue-5746-anon-seed-scope-measurement at packages/app-shell/src/console/__tests__/anonSeedScope-5746.enumeration.test.tsx.

Worth considering — as a recommendation, not a decision — landing it as a regression pin alongside whatever this card rules, given that the main safety property now rests on a single mechanism. Two instrument defects it already caught are documented in its own comments, both of which would otherwise have produced a false "no writes anywhere" reading: jsdom hands out sessionStorage as a Proxy (so this === sessionStorage is never true inside a Storage.prototype method), and vi.restoreAllMocks() does not undo a reassigned property.

Refs: #5746 (parent, closed latent-not-live) · #5198 (the principal-scoped key) · #5744 (the purge that does not cover this) · #4042 (the session gate that shuts both named windows).


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:queuesecurity

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions