remotion-dev/remotion · error · Error
Path is outside of the parent directory - not allowing readi
Error message
Path is outside of the parent directory - not allowing reading of arbitrary files
What it means
Thrown by nodeCreateAdjacentFileSource as a security guard after computing the adjacent path: it joins relativePath with dirname(src), then checks the result with path.relative; if the result starts with '..' it means the requested file would escape the media's parent directory, which is treated as an arbitrary-file-read attempt and rejected.
Source
Thrown at packages/media-parser/src/readers/from-node.ts:126
if (typeof src !== 'string') {
throw new Error('src must be a string when using `nodeReader`');
}
return promises.readFile(src, 'utf8');
};
export const nodeCreateAdjacentFileSource: CreateAdjacentFileSource = (
relativePath,
src,
) => {
if (typeof src !== 'string') {
throw new Error('src must be a string when using `nodeReader`');
}
const result = join(dirname(src), relativePath);
const rel = relative(dirname(src), result);
if (rel.startsWith('..')) {
throw new Error(
'Path is outside of the parent directory - not allowing reading of arbitrary files',
);
}
return result;
};
export const nodeReader: MediaParserReaderInterface = {
read: nodeReadContent,
readWholeAsText: nodeReadWholeAsText,
createAdjacentFileSource: nodeCreateAdjacentFileSource,
preload: () => {
// doing nothing, it's just for when fetching over the network
},
};
View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Treat the error as intentional: do not weaken it. Ensure the adjacent file legitimately lives under the media's parent directory.
- If you control the companion path, use a path that stays within dirname(src), e.g. 'subtitles/en.vtt' not '../shared/en.vtt'.
- For untrusted media, run the parser in a sandbox with a restricted root, and reject inputs that trigger this guard.
Example fix
// before - companion path escapes parent dir adjacent: '../shared/captions.vtt' // -> throws // after - companion path stays under parent dir adjacent: 'captions.vtt'
Defensive patterns
Strategy: try-catch
Validate before calling
import { relative, dirname, join, resolve } from 'node:path';
function isSafeAdjacent(mediaSrc: string, rel: string): boolean {
const base = resolve(dirname(mediaSrc));
const target = resolve(base, rel);
const rel2 = relative(base, target);
return !rel2.startsWith('..') && !resolve(rel).startsWith('/');
}
isSafeAdjacent(src, companionRel); Type guard
const staysInParent = (base: string, target: string) => !relative(base, target).startsWith('..'); Try / catch
try { await parseMedia({ src, fields }); } catch (e) { if (/outside of the parent directory/.test(String((e as Error).message))) { /* reject untrusted media or use inline assets */ } else throw e; } Prevention
- Treat this guard as a security feature; never bypass it.
- Run parsers over untrusted media in a sandbox with a restricted root.
- Prefer self-contained (inline) media to avoid adjacent-file references.
When it happens
Trigger: A media container references an adjacent file via a path containing '../' sequences or an absolute path that resolves outside the media's directory. For example, a crafted file listing 'tracks/../../etc/passwd' or '/etc/secret' as a companion resource.
Common situations: Parsing untrusted user-uploaded media whose metadata embeds path-traversal payloads. Bugs in relative-path computation that prepend too many '..' segments. Absolute paths supplied where relatives are expected.
Related errors
- src must be a string when using `nodeReader`
- File does not exist: ${src}
- Invalid public file path: ${path}
- Not enough bytes left to parse EBML - this should not happen
- has no bytes
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/bfa0a8cc5fd0a04a.
Report an issue: GitHub.