{"record":{"id":"29ec994e814093ad","repo":"mastra-ai/mastra","slug":"extractor-metadatakeypath-keypath-contains-an","errorCode":null,"errorMessage":"Extractor metadataKeyPath \"${keyPath}\" contains an unsafe path segment.","messagePattern":"Extractor metadataKeyPath \"(.+?)\" contains an unsafe path segment\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/memory/src/processors/observational-memory/extracted-values.ts","lineNumber":80,"sourceCode":"}\n\nexport function mergeExtractionFailures(\n  ...failureSets: Array<ExtractionFailure[] | undefined>\n): ExtractionFailure[] | undefined {\n  const failures = failureSets.flatMap(set => set ?? []);\n  return failures.length > 0 ? failures : undefined;\n}\n\nconst UNSAFE_METADATA_PATH_SEGMENTS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction getMetadataPathSegments(keyPath: string | false): string[] | undefined {\n  if (keyPath === false) {\n    return undefined;\n  }\n\n  const segments = keyPath.split('.').filter(Boolean);\n  if (segments.some(segment => UNSAFE_METADATA_PATH_SEGMENTS.has(segment))) {\n    throw new Error(`Extractor metadataKeyPath \"${keyPath}\" contains an unsafe path segment.`);\n  }\n  return segments.length > 0 ? segments : undefined;\n}\n\nfunction getValueAtPath(metadata: ExtractedValueMetadata | undefined, keyPath: string | false): unknown {\n  if (!metadata) {\n    return undefined;\n  }\n\n  const segments = getMetadataPathSegments(keyPath);\n  if (!segments) {\n    return undefined;\n  }\n\n  let current: unknown = metadata;\n  for (const segment of segments) {\n    if (!current || typeof current !== 'object' || Array.isArray(current)) {\n      return undefined;","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/extracted-values.ts#L62-L98","documentation":"When observational memory applies extractors, each extractor's metadataKeyPath (a dot-delimited path into extracted-value metadata) is split into segments and validated against a set of unsafe path segments (e.g. prototype-pollution names like __proto__/constructor). A path containing such a segment is rejected to prevent unsafe property traversal.","triggerScenarios":"Configuring an Extractor whose metadataKeyPath includes a segment like \"__proto__\", \"constructor\", or another entry in UNSAFE_METADATA_PATH_SEGMENTS; building key paths dynamically from user input that contains such tokens.","commonSituations":"Dynamically deriving metadataKeyPath from user-supplied field names; typos or copy-paste introducing reserved segment names; security tooling flagging and then someone 'testing' with prototype-pollution payloads.","solutions":["Change the metadataKeyPath to use only safe identifier segments (no __proto__, constructor, prototype, etc.)","Sanitize/allowlist user-derived path segments before building the key path","If you need to store such a key, encode or prefix it (e.g. 'data.constructor_name') so it no longer collides with unsafe segments"],"exampleFix":"// before\nnew Extractor({ name: 'profile', metadataKeyPath: 'user.__proto__.name', ... });\n\n// after\nnew Extractor({ name: 'profile', metadataKeyPath: 'user.profile.name', ... });","handlingStrategy":"validation","validationCode":"const UNSAFE = new Set(['__proto__', 'constructor', 'prototype']);\nconst isSafeKeyPath = (p: string) => p.split('.').filter(Boolean).every(s => !UNSAFE.has(s));\nif (!isSafeKeyPath(extractorConfig.metadataKeyPath)) throw new Error('metadataKeyPath has an unsafe segment');","typeGuard":null,"tryCatchPattern":"try {\n  registerExtractor(cfg);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('unsafe path segment')) {\n    console.error(`Rejecting extractor with unsafe metadataKeyPath: ${cfg.metadataKeyPath}`);\n  }\n  throw err;\n}","preventionTips":["Allowlist metadataKeyPath segments against a safe identifier regex /^[A-Za-z_][A-Za-z0-9_]*$/","Never build metadataKeyPath directly from raw user input","Add a unit test covering prototype-pollution payloads for extractor configs"],"tags":["observational-memory","security","prototype-pollution","input-validation"],"backgroundTag":"unsafe-path-segment","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}