apify/crawlee · error · Error
"${segment}" is not allowed because it would resolve outside
Error message
"${segment}" is not allowed because it would resolve outside of the storage directory. Storage names and record keys must not contain path traversal segments ("..") or absolute paths. What it means
resolveWithinDirectory joins a user-supplied name/key onto a base storage directory and verifies the result stays inside that base. This guards the memory-storage implementation against path traversal: names containing '..' or absolute paths could read/write files outside the storage directory. Any storage name, queue id, or record key that escapes the base is rejected.
Source
Thrown at packages/core/src/memory-storage/utils.ts:16
import { createHash } from 'node:crypto';
import { resolve, sep } from 'node:path';
import { REQUEST_ID_LENGTH } from './consts.js';
/**
* Resolves `segment` against `baseDirectory` and ensures the result stays within `baseDirectory`.
* Storage names and record keys are used as filesystem path components, so a value containing `..`
* or an absolute path could otherwise escape the intended directory.
*/
export function resolveWithinDirectory(baseDirectory: string, segment: string): string {
const base = resolve(baseDirectory);
const resolved = resolve(base, segment);
if (resolved !== base && !resolved.startsWith(`${base}${sep}`)) {
throw new Error(
`"${segment}" is not allowed because it would resolve outside of the storage directory. ` +
`Storage names and record keys must not contain path traversal segments ("..") or absolute paths.`,
);
}
return resolved;
}
/**
* Removes all properties with a null value
* from the provided object.
*/
export function purgeNullsFromObject<T>(object: T): T {
if (object && typeof object === 'object' && !Array.isArray(object)) {
for (const [key, value] of Object.entries(object)) {
if (value === null) Reflect.deleteProperty(object as Record<string, unknown>, key);
}
}View on GitHub (pinned to dbe57fb09c)
Solutions
- Sanitize the name/key: strip or reject '..' segments, leading '/', and drive letters before passing it.
- Use only alphanumeric, dash, and underscore characters for storage names and record keys.
- If nested organization is needed, create separate storages instead of encoding paths in the name.
- Validate untrusted input at the boundary (e.g. a schema with a regex like /^[A-Za-z0-9_-]+$/).
Example fix
// before
const store = await MemoryStorage.openStore(userInput); // '../other'
// after
const name = userInput.replace(/[^A-Za-z0-9_-]/g, '');
if (!name) throw new Error('Invalid storage name');
const store = await MemoryStorage.openStore(name); Defensive patterns
Strategy: validation
Validate before calling
function isSafeStorageName(name) {
return typeof name === 'string' && /^[A-Za-z0-9_-]+$/.test(name);
}
if (!isSafeStorageName(userInput)) throw new Error('Invalid storage name'); Type guard
function isSafeStorageSegment(s: unknown): s is string {
return typeof s === 'string' && s.length > 0 && !s.includes('..') && !s.startsWith('/') && !s.includes('\\') && /^[A-Za-z0-9_-]+$/.test(s);
} Try / catch
try {
return resolveWithinDirectory(base, segment);
} catch (err) {
if ((err as Error).message.includes('would resolve outside of the storage directory')) {
throw new ValidationError(`Unsafe storage key: ${segment}`);
}
throw err;
} Prevention
- Restrict storage names/keys to [A-Za-z0-9_-].
- Never pass raw user input as a storage name or record key.
- Sanitize at the API boundary before any storage call.
- Treat traversal attempts as security events and log them.
When it happens
Trigger: Passing a storage name or record key containing '..' (e.g. '../secrets'), an absolute path ('/etc/passwd'), or on Windows a drive-qualified path to MemoryStorage APIs such as opening a store/queue/dataset with such a name, or accessing a record whose key resolves outside the base directory.
Common situations: User-supplied storage names passed straight from input into MemoryStorage; keys built by string concatenation with unsanitized segments; attempting to alias one store to another path via traversal; security testing of crawlee memory storage.
Related errors
- Failed to infer format from the path: '${path}'. Supported f
- Unsupported format: '${format}'. Use one of ${supportedForma
- Invalid "proxyUrl". Unsupported protocol: ${proxyUrl}.
- Invalid "proxyUrl" option: authentication is only supported
- The project name cannot be empty string.
AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30).
Data as JSON: /api/errors/af5ba8aff04902f9.
Report an issue: GitHub.