# Risk map — pmndrs/zustand

> Canonical page: https://codevetter.com/unpack/zustand/risk-map

# Risk map — pmndrs/zustand

Scanned commit d7a5583cffd80af515f7dfb69583c95cbdc9e2ce (2026-09-29). Generated by codevetter codevetter 1.15.0 on 2026-10-02.

Source inspection; upstream code and tests were not executed.

The material boundaries inspected are persisted data, browser-extension messages, server store ownership, and synchronous update propagation. These are source observations and explicitly identified hypotheses, not confirmed vulnerabilities. Packaging and examples also expose verification limits; the bounded inspection does not establish whole-repository absence of other sensitive paths.
- The persistence default writes the whole state to localStorage through JSON serialization; applications must use partialize or an appropriate adapter when state contains data that should not be stored there. — [src/middleware/persist.ts#L187-L198](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L187-L198) [src/middleware/persist.ts#L221-L226](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L221-L226) [src/middleware/persist.ts#L56-L58](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L56-L58)
- Stored JSON is parsed and type-asserted without runtime schema validation; default hydration spreads persisted values over current state, so validation and domain-specific merge behavior belong at the adapter/migration/merge boundary. — [src/middleware/persist.ts#L43-L54](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L43-L54) [src/middleware/persist.ts#L102-L110](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L102-L110) [src/middleware/persist.ts#L193-L196](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L193-L196) [src/middleware/persist.ts#L302-L307](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L302-L307)
- Persistence updates live state before setItem; a serialization or storage-write failure occurs after the in-memory update, with no rollback in these wrappers. — [src/middleware/persist.ts#L221-L239](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L221-L239) [src/middleware/persist.ts#L56-L57](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L56-L57)
- Hydration generations prevent stale hydration application, but default merge still overwrites concurrent edits to stored keys; the test titled 'should not overwrite user state changes' actually expects count 100 to become 42. — [src/middleware/persist.ts#L193-L196](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L193-L196) [src/middleware/persist.ts#L297-L307](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/persist.ts#L297-L307) [tests/persistAsync.test.tsx#L981-L1020](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/tests/persistAsync.test.tsx#L981-L1020)
- DevTools receives full state snapshots and accepts incoming state-changing messages; production-default disabling and JSON parse error handling do not provide application-state schema validation. — [src/middleware/devtools.ts#L198-L209](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/devtools.ts#L198-L209) [src/middleware/devtools.ts#L230-L243](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/devtools.ts#L230-L243) [src/middleware/devtools.ts#L317-L345](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/devtools.ts#L317-L345) [src/middleware/devtools.ts#L426-L436](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/devtools.ts#L426-L436)
- The Next.js guide requires per-request stores and warns against RSC access to shared stores; unstable_ssrSafe rejects SSR writes but does not itself create request isolation. — [docs/learn/guides/nextjs.md#L15-L35](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/docs/learn/guides/nextjs.md#L15-L35) [src/middleware/ssrSafe.ts#L13-L23](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/middleware/ssrSafe.ts#L13-L23)
- Hypothesis: a throwing synchronous listener can interrupt later listener notifications after state has already changed, because setState calls listeners.forEach without per-listener exception isolation. (inferred) — [src/vanilla.ts#L73-L79](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/src/vanilla.ts#L73-L79)
- Verification limits include a development-only built-package matrix and root checks that exclude examples; demo declares Zustand ^4.3.9 while the library is 5.0.15, so its behavior cannot establish current-source parity. — [.github/workflows/test-multiple-builds.yml#L17-L19](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/.github/workflows/test-multiple-builds.yml#L17-L19) [eslint.config.mjs#L11-L12](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/eslint.config.mjs#L11-L12) [tsconfig.json#L23-L24](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/tsconfig.json#L23-L24) [examples/demo/package.json#L25-L28](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/examples/demo/package.json#L25-L28)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
