Budibase/budibase · error · HTTPError
Project package contains unsafe paths.
Error message
Project package contains unsafe paths.
What it means
While recursively reading the extracted package, every path is relativized to the archive root and checked with isSafeArchivePath. If a path escapes the root (e.g. .. traversal, absolute paths) the import aborts with this 400 HTTPError. This prevents zip/tar-slip attacks where a malicious archive writes files outside the target directory.
Source
Thrown at packages/server/src/sdk/workspace/projects/backups/imports.ts:187
!path.startsWith("\\") &&
!/^[A-Za-z]:/.test(path) &&
segments.every(segment => segment !== ".." && segment !== ".")
)
}
const readDirectoryRecursively = async (
dirPath: string,
rootPath = dirPath,
totals = { files: 0, bytes: 0 }
): Promise<string[]> => {
const entries = await fsp.readdir(dirPath, { withFileTypes: true })
const files: string[] = []
for (const entry of entries) {
const fullPath = join(dirPath, entry.name)
const relPath = relative(rootPath, fullPath)
if (!isSafeArchivePath(relPath)) {
throw new HTTPError("Project package contains unsafe paths.", 400)
}
if (relPath.split(/[\\/]/).length > MAX_PATH_SEGMENTS) {
throw new HTTPError(
"Project package contains paths that are too deep.",
400
)
}
if (entry.isSymbolicLink()) {
throw new HTTPError("Project package contains unsupported links.", 400)
}
if (entry.isDirectory()) {
files.push(
...(await readDirectoryRecursively(fullPath, rootPath, totals))
)
} else {
const stats = await fsp.stat(fullPath)
totals.files += 1
totals.bytes += stats.sizeView on GitHub (pinned to a81a902e9a)
Solutions
- Inspect the archive listing (tar -tf) for entries with .. or absolute paths and remove them
- Regenerate the package with Budibase's own export flow
- Only import packages from trusted sources
- Sanitize entry names to be relative and contained within the archive root
Example fix
// before // archive entry: ../../etc/passwd // after // archive entry: files/etc-passwd (relative, inside package root)
Defensive patterns
Strategy: validation
Validate before calling
import { isSafeArchivePath } from "@budibase/backend-core" // same guard the importer uses
for (const entry of entries) {
if (!isSafeArchivePath(relative(root, entry))) throw new Error(`Unsafe archive entry: ${entry}`)
} Type guard
function isContainedPath(relPath: string): boolean {
return !!relPath && !relPath.startsWith("..") && !isAbsolute(relPath)
} Try / catch
try {
await importProject(packagePath)
} catch (e) {
if (e instanceof HTTPError && e.message.includes("unsafe paths")) {
// reject/inspect the untrusted package — do not retry as-is
} else throw e
} Prevention
- Only import packages from trusted sources
- Inspect archives (tar -tf) for ../ or absolute entries before import
- Build packages with Budibase export, not custom scripts
When it happens
Trigger: Importing a package whose archive entries contain path traversal (../), absolute paths, or names that relativize outside rootPath — typically a deliberately malicious or improperly generated archive.
Common situations: Third-party or tampered .tar.gz packages; archives built on Windows with odd separators/absolute entries; custom scripts that add entries with leading '/' or '..' components.
Related errors
- Project package contains unsupported links.
- Invalid object store key: path traversal is not allowed.
- Only HTTP(S) URLs are allowed for query import
- Import url must not contain credentials
- Project package contains invalid JSON in '${basename(filePat
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/e8c337af6db17aa3.
Report an issue: GitHub.