Skip to content

fix(security): harden Live Components with 4 high-priority security improvements#64

Merged
MarcosBrendonDePaula merged 5 commits intomainfrom
claude/secure-live-components-7Uz81
Feb 21, 2026
Merged

fix(security): harden Live Components with 4 high-priority security improvements#64
MarcosBrendonDePaula merged 5 commits intomainfrom
claude/secure-live-components-7Uz81

Conversation

@MarcosBrendonDePaula
Copy link
Copy Markdown
Collaborator

  1. Anti-replay on rehydration: Add cryptographic nonce to signed state.
    Each signed state now includes a random 128-bit nonce that is consumed
    on validation, preventing the same signed state from being replayed.
    Expired nonces are cleaned up daily to prevent memory growth.

  2. Magic bytes content validation for uploads: Validate actual file content
    against known magic byte signatures (JPEG, PNG, GIF, WebP, PDF, ZIP, GZIP)
    instead of trusting only the MIME type header. Also detect double extension
    bypass attacks (e.g., malware.exe.jpg).

  3. Per-user upload quota: Enforce 500MB/day upload limit per user to prevent
    disk exhaustion attacks. Quotas are tracked by userId and reset daily.

  4. Mandatory publicActions whitelist: Components without publicActions now
    deny ALL remote actions (secure by default). Previously, missing
    publicActions would fall back to blocklist-only mode which is more fragile.
    All existing components updated with explicit publicActions declarations.

https://claude.ai/code/session_0193vWzJM26QCwN4K9P7rQP3

…mprovements

1. Anti-replay on rehydration: Add cryptographic nonce to signed state.
   Each signed state now includes a random 128-bit nonce that is consumed
   on validation, preventing the same signed state from being replayed.
   Expired nonces are cleaned up daily to prevent memory growth.

2. Magic bytes content validation for uploads: Validate actual file content
   against known magic byte signatures (JPEG, PNG, GIF, WebP, PDF, ZIP, GZIP)
   instead of trusting only the MIME type header. Also detect double extension
   bypass attacks (e.g., malware.exe.jpg).

3. Per-user upload quota: Enforce 500MB/day upload limit per user to prevent
   disk exhaustion attacks. Quotas are tracked by userId and reset daily.

4. Mandatory publicActions whitelist: Components without publicActions now
   deny ALL remote actions (secure by default). Previously, missing
   publicActions would fall back to blocklist-only mode which is more fragile.
   All existing components updated with explicit publicActions declarations.

https://claude.ai/code/session_0193vWzJM26QCwN4K9P7rQP3
- Component generator (make:live): All 4 templates now include
  static publicActions with the appropriate methods listed

- LLMD/resources/live-components.md: publicActions documented as
  mandatory in Quick Facts, class structure, Actions section, setValue
  note, component organization, and Critical Rules

- LLMD/resources/live-upload.md: Added Security Features section with
  magic bytes table, per-user quota docs, double extension prevention,
  updated chunked upload flow, and error handling examples

- LLMD/patterns/anti-patterns.md: New "Live Component Security
  Anti-Patterns" section covering missing publicActions, unsafe
  setValue usage, MIME type trust, and double extensions

- LLMD/resources/live-auth.md: Added publicActions to all code examples,
  new "Security Layers" section documenting action execution order,
  updated auth flow diagram and Critical Rules

https://claude.ai/code/session_0193vWzJM26QCwN4K9P7rQP3
The client-side ExtractActions<T> type previously extracted ALL public
async methods from the server component class, ignoring publicActions.
This caused TypeScript to autocomplete methods that the server would
reject at runtime.

Now:
- If publicActions is defined: only those methods appear in the type
- If publicActions is NOT defined: Record<string, never> (no actions)

This matches the server-side enforcement where components without
publicActions deny ALL remote actions (secure by default).

https://claude.ai/code/session_0193vWzJM26QCwN4K9P7rQP3
Adds a $private key-value store on LiveComponent that never syncs with
the client. Sensitive data like tokens and API keys can now be stored
server-side without leaking via STATE_UPDATE/STATE_DELTA messages.

- Add _privateState field and $private getter to LiveComponent
- Block $private and _privateState in BLOCKED_ACTIONS and forbidden set
- Clear _privateState on destroy()
- Add 16 tests covering isolation, security, and lifecycle
- Update live-components.md and anti-patterns.md docs

https://claude.ai/code/session_0193vWzJM26QCwN4K9P7rQP3
The second generic parameter on LiveComponent enables full autocomplete
and type checking for server-only private state. Defaults to
Record<string, any> so existing components need no changes.

Usage: LiveComponent<State, { token: string; apiKey: string }>

- Add TPrivate generic with default Record<string, any>
- Add InferPrivateState<T> utility type
- Add typed $private tests (22 total, 6 new)
- Update live-components.md with typed $private section
- TypeScript compilation passes with zero errors

https://claude.ai/code/session_0193vWzJM26QCwN4K9P7rQP3
@MarcosBrendonDePaula MarcosBrendonDePaula merged commit 27e8f44 into main Feb 21, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants