solidjs/solid · warning
Refusing to traverse unsafe key "${part}" on a store.
Error message
Refusing to traverse unsafe key "${part}" on a store. What it means
updatePath, which walks setter paths like setStore('a', 'b', value), refuses to traverse __proto__ (always) and other unsafe keys (constructor/prototype-style keys when further path segments follow), warning in dev. Traversing such keys would walk up the prototype chain and write outside the store's own data, a prototype-pollution vector.
Source
Thrown at packages/solid/store/src/store.ts:303
len = next.length;
for (; i < len; i++) {
const value = next[i];
if (current[i] !== value) setProperty(current, i, value);
}
setProperty(current, "length", len);
} else mergeStoreNode(current, next);
}
export function updatePath(current: StoreNode, path: any[], traversed: PropertyKey[] = []) {
let part,
prev = current;
if (path.length > 1) {
part = path.shift();
const partType = typeof part,
isArray = Array.isArray(current);
if (partType === "string" && (part === "__proto__" || (path.length > 1 && isUnsafeKey(part)))) {
if (IS_DEV) console.warn(`Refusing to traverse unsafe key "${part}" on a store.`);
return;
}
if (Array.isArray(part)) {
// Ex. update('data', [2, 23], 'label', l => l + ' !!!');
for (let i = 0; i < part.length; i++) {
updatePath(current, [part[i]].concat(path), traversed);
}
return;
} else if (isArray && partType === "function") {
// Ex. update('data', i => i.id === 42, 'label', l => l + ' !!!');
for (let i = 0; i < current.length; i++) {
if (part(current[i], i)) updatePath(current, [i].concat(path), traversed);
}
return;
} else if (isArray && partType === "object") {
// Ex. update('data', { from: 3, to: 12, by: 2 }, 'label', l => l + ' !!!');
const { from = 0, to = current.length - 1, by = 1 } = part;View on GitHub (pinned to f47845f9cc)
Solutions
- Validate path segments against /^[A-Za-z0-9_$-]+$/ or a whitelist before calling setStore
- Block __proto__/constructor/prototype keys at the API boundary
- Use produce for deep programmatic edits rather than dynamic key paths
Example fix
// before
function deepSet(store, path, value) {
setStore(...path.split('.'), value); // 'a.__proto__.x' traverses
}
// after
const UNSAFE = ['__proto__', 'constructor', 'prototype'];
function deepSet(setStore, path, value) {
const parts = path.split('.');
if (parts.some(p => UNSAFE.includes(p))) throw new Error('unsafe path');
setStore(...parts, value);
} Defensive patterns
Strategy: validation
Validate before calling
const UNSAFE = ['__proto__', 'constructor', 'prototype'];
function deepSet(setStore: Function, pathStr: string, value: unknown) {
const parts = pathStr.split('.');
if (parts.some(p => !p.length || UNSAFE.includes(p))) throw new Error('unsafe store path');
setStore(...parts, value);
} Type guard
const isSafePath = (parts: string[]): boolean => parts.every(p => /^[A-Za-z0-9_$-]+$/.test(p) && !['__proto__', 'constructor', 'prototype'].includes(p));
Prevention
- Validate path segments from user/network input before setStore
- Never forward raw dot-split keys into store paths
- Use produce for deep programmatic updates
When it happens
Trigger: setStore('__proto__', 'polluted', true); setStore('constructor', 'prototype', x); or building a path array from unvalidated user input (dot-split body keys like user-provided 'a.__proto__.b').
Common situations: Generic deep-set helpers that split key strings on dots and forward to setStore; accepting nested updates from APIs/websockets; porting MongoDB-style update operators into store updates.
Related errors
- Refusing to set "__proto__" on a store.
- Cannot mutate a Store directly
- Unexpected type ${typeof unwrappedStore} received when initi
- Unexpected type ${typeof unwrappedStore} received when initi
- error handlers created outside a `createRoot` or `render` wi
AI-assisted analysis of solidjs/solid@f47845f9cc (2026-08-27).
Data as JSON: /api/errors/bcebd86fefa28945.
Report an issue: GitHub.