Budibase/budibase · error
Invalid object store key: path traversal is not allowed.
Error message
Invalid object store key: path traversal is not allowed.
What it means
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.
Source
Thrown at packages/backend-core/src/objectStore/objectStore.ts:101
form: "multipart/form-data",
}
const STRING_CONTENT_TYPES = [
CONTENT_TYPE_MAP.html,
CONTENT_TYPE_MAP.css,
CONTENT_TYPE_MAP.js,
CONTENT_TYPE_MAP.json,
]
// does normal sanitization and then swaps dev apps to apps
export function sanitizeKey(input: string): string {
const key = sanitize(sanitizeBucket(input)).replace(/\\/g, "/")
if (
key
.split("/")
.some((segment: string) => segment === "." || segment === "..")
) {
throw new Error("Invalid object store key: path traversal is not allowed.")
}
return key
}
// simply handles the dev app to app conversion
export function sanitizeBucket(input: string): string {
return input.replace(new RegExp(WORKSPACE_DEV_PREFIX, "g"), WORKSPACE_PREFIX)
}
/**
* Gets a connection to the object store using the S3 SDK.
* @param bucket the name of the bucket which blobs will be uploaded/retrieved from.
* @param opts configuration for the object store.
* @return an S3 object store object, check S3 Nodejs SDK for usage.
* @constructor
*/
export function ObjectStore(
opts: { presigning: boolean } = { presigning: false }View on GitHub (pinned to a81a902e9a)
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
Example fix
// before
await upload({ bucket, filename: userProvidedName }) // "../../evil"
// after
const safeName = path.posix.basename(userProvidedName).replace(/\.+/g, "_")
await upload({ bucket, filename: `${uuid()}__${safeName}` }) Defensive patterns
Strategy: validation
Validate before calling
function assertSafeKey(input) {
const segments = input.replace(/\\/g, "/").split("/")
if (segments.some(s => s === "." || s === "..")) {
throw new Error("key contains path traversal segments")
}
} Type guard
function isSafeKey(key: string): boolean {
return key.replace(/\\/g, "/").split("/").every(s => s !== "." && s !== "..")
} Try / catch
try {
await objectStore.deleteFile(bucket, key)
} catch (err) {
if (String(err.message).startsWith("Invalid object store key")) {
// treat as a client error: reject the request, do not retry
}
} Prevention
- 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'
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Stream to upload is invalid/undefined
- Only HTTP(S) URLs are allowed.
- Only HTTP(S) URLs are allowed for query import
- Import url must not contain credentials
- File "${fileName}" has an invalid extension: "${extension}"
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/a3c02aa646ec1795.
Report an issue: GitHub.