{"record":{"id":"a3c02aa646ec1795","repo":"Budibase/budibase","slug":"invalid-object-store-key-path-traversal-is-not-al","errorCode":null,"errorMessage":"Invalid object store key: path traversal is not allowed.","messagePattern":"Invalid object store key: path traversal is not allowed\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/backend-core/src/objectStore/objectStore.ts","lineNumber":101,"sourceCode":"  form: \"multipart/form-data\",\n}\n\nconst STRING_CONTENT_TYPES = [\n  CONTENT_TYPE_MAP.html,\n  CONTENT_TYPE_MAP.css,\n  CONTENT_TYPE_MAP.js,\n  CONTENT_TYPE_MAP.json,\n]\n\n// does normal sanitization and then swaps dev apps to apps\nexport function sanitizeKey(input: string): string {\n  const key = sanitize(sanitizeBucket(input)).replace(/\\\\/g, \"/\")\n  if (\n    key\n      .split(\"/\")\n      .some((segment: string) => segment === \".\" || segment === \"..\")\n  ) {\n    throw new Error(\"Invalid object store key: path traversal is not allowed.\")\n  }\n  return key\n}\n\n// simply handles the dev app to app conversion\nexport function sanitizeBucket(input: string): string {\n  return input.replace(new RegExp(WORKSPACE_DEV_PREFIX, \"g\"), WORKSPACE_PREFIX)\n}\n\n/**\n * Gets a connection to the object store using the S3 SDK.\n * @param bucket the name of the bucket which blobs will be uploaded/retrieved from.\n * @param opts configuration for the object store.\n * @return an S3 object store object, check S3 Nodejs SDK for usage.\n * @constructor\n */\nexport function ObjectStore(\n  opts: { presigning: boolean } = { presigning: false }","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/backend-core/src/objectStore/objectStore.ts#L83-L119","documentation":"sanitizeKey normalizes object store keys and then rejects any key whose path segments contain '.' or '..', since S3-style keys are used to build filesystem/storage paths and traversal could escape the intended bucket prefix. This is a deliberate security guard against path traversal.","triggerScenarios":"Calling any objectStore operation that takes a key (upload, download, delete, headDetails, clientLibraryPath, client3rdPartyLibrary) with a filename containing '../' or a '.'/'..' segment after backslash-to-slash normalization.","commonSituations":"User-supplied filenames containing '../' (e.g. uploads named '../../etc/passwd'); importing app data with crafted keys; Windows-style paths using backslashes that normalize into traversal; client library paths built from untrusted package names.","solutions":["Sanitize the filename before calling object store APIs — strip path components and use only the base name","Generate your own safe key (e.g. uuid or hash-based) instead of using raw user input as the key","Reject the request upstream with a validation error if it contains '.' or '..' segments","Audit data sources feeding keys (imports, package names) for traversal payloads"],"exampleFix":"// before\nawait upload({ bucket, filename: userProvidedName }) // \"../../evil\"\n// after\nconst safeName = path.posix.basename(userProvidedName).replace(/\\.+/g, \"_\")\nawait upload({ bucket, filename: `${uuid()}__${safeName}` })","handlingStrategy":"validation","validationCode":"function assertSafeKey(input) {\n  const segments = input.replace(/\\\\/g, \"/\").split(\"/\")\n  if (segments.some(s => s === \".\" || s === \"..\")) {\n    throw new Error(\"key contains path traversal segments\")\n  }\n}","typeGuard":"function isSafeKey(key: string): boolean {\n  return key.replace(/\\\\/g, \"/\").split(\"/\").every(s => s !== \".\" && s !== \"..\")\n}","tryCatchPattern":"try {\n  await objectStore.deleteFile(bucket, key)\n} catch (err) {\n  if (String(err.message).startsWith(\"Invalid object store key\")) {\n    // treat as a client error: reject the request, do not retry\n  }\n}","preventionTips":["Never use raw user input as an object store key; generate uuid/hash-based keys","Strip directory components (basename) from user-supplied filenames before upload","Validate keys for '.'/'..' segments at the API boundary, before persistence","Security-test import/upload endpoints with payloads like '../../x'"],"tags":["security","path-traversal","validation","object-store"],"backgroundTag":"path-traversal-detected","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}