{"record":{"id":"bcebd86fefa28945","repo":"solidjs/solid","slug":"refusing-to-traverse-unsafe-key-part-on-a-sto","errorCode":null,"errorMessage":"Refusing to traverse unsafe key \"${part}\" on a store.","messagePattern":"Refusing to traverse unsafe key \"(.+?)\" on a store\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/solid/store/src/store.ts","lineNumber":303,"sourceCode":"      len = next.length;\n    for (; i < len; i++) {\n      const value = next[i];\n      if (current[i] !== value) setProperty(current, i, value);\n    }\n    setProperty(current, \"length\", len);\n  } else mergeStoreNode(current, next);\n}\n\nexport function updatePath(current: StoreNode, path: any[], traversed: PropertyKey[] = []) {\n  let part,\n    prev = current;\n  if (path.length > 1) {\n    part = path.shift();\n    const partType = typeof part,\n      isArray = Array.isArray(current);\n\n    if (partType === \"string\" && (part === \"__proto__\" || (path.length > 1 && isUnsafeKey(part)))) {\n      if (IS_DEV) console.warn(`Refusing to traverse unsafe key \"${part}\" on a store.`);\n      return;\n    }\n\n    if (Array.isArray(part)) {\n      // Ex. update('data', [2, 23], 'label', l => l + ' !!!');\n      for (let i = 0; i < part.length; i++) {\n        updatePath(current, [part[i]].concat(path), traversed);\n      }\n      return;\n    } else if (isArray && partType === \"function\") {\n      // Ex. update('data', i => i.id === 42, 'label', l => l + ' !!!');\n      for (let i = 0; i < current.length; i++) {\n        if (part(current[i], i)) updatePath(current, [i].concat(path), traversed);\n      }\n      return;\n    } else if (isArray && partType === \"object\") {\n      // Ex. update('data', { from: 3, to: 12, by: 2 }, 'label', l => l + ' !!!');\n      const { from = 0, to = current.length - 1, by = 1 } = part;","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/solidjs/solid/blob/f47845f9cc16ecbb316aa6560c7161f45af9a3d8/packages/solid/store/src/store.ts#L285-L321","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","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"],"exampleFix":"// before\nfunction deepSet(store, path, value) {\n  setStore(...path.split('.'), value); // 'a.__proto__.x' traverses\n}\n\n// after\nconst UNSAFE = ['__proto__', 'constructor', 'prototype'];\nfunction deepSet(setStore, path, value) {\n  const parts = path.split('.');\n  if (parts.some(p => UNSAFE.includes(p))) throw new Error('unsafe path');\n  setStore(...parts, value);\n}","handlingStrategy":"validation","validationCode":"const UNSAFE = ['__proto__', 'constructor', 'prototype'];\nfunction deepSet(setStore: Function, pathStr: string, value: unknown) {\n  const parts = pathStr.split('.');\n  if (parts.some(p => !p.length || UNSAFE.includes(p))) throw new Error('unsafe store path');\n  setStore(...parts, value);\n}","typeGuard":"const isSafePath = (parts: string[]): boolean =>\n  parts.every(p => /^[A-Za-z0-9_$-]+$/.test(p) && !['__proto__', 'constructor', 'prototype'].includes(p));","tryCatchPattern":null,"preventionTips":["Validate path segments from user/network input before setStore","Never forward raw dot-split keys into store paths","Use produce for deep programmatic updates"],"tags":["solid","store","prototype-pollution","security","dev-warning"],"backgroundTag":"prototype-pollution-guard","analyzedSha":"f47845f9cc16ecbb316aa6560c7161f45af9a3d8","analyzedAt":"2026-08-27T05:39:24.283Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}