ComposioHQ/composio · error · ComposioFileUploadPathNotAllowedError
Refusing to auto-upload
Error message
Refusing to auto-upload "${attempted}": resolved path is not inside any
directory in the configured `fileUploadDirs` allowlist.
Path attempted: ${attempted}
Resolved to: ${real}
${buildHelpFooter(allowlist)} What it means
assertPathInsideUploadDirs throws ComposioFileUploadPathNotAllowedError when the file exists but its realpath is not inside any configured fileUploadDirs entry (after symlink resolution via realpath on both sides).
Solutions
- Add the file's actual directory (the 'Resolved to' path's parent) to fileUploadDirs
- Use absolute, realpath-resolved paths in the allowlist (fs.realpathSync) to defeat symlink mismatches
- Widen deliberately, e.g. add os.tmpdir() if tools write temp files there
- Never work around by symlinking files into the allowlisted dir; configure the real location
Example fix
// before
new Composio({ apiKey, fileUploadDirs: ['/tmp'] }); // macOS: /tmp -> /private/tmp
// after
new Composio({ apiKey, fileUploadDirs: [fs.realpathSync('/tmp')] }); Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:path';
function isUploadable(p: string, dirs: string[]): boolean {
const real = fs.realpathSync(p);
return dirs.some((d) => real.startsWith(fs.realpathSync(d) + fs.sep));
} Try / catch
catch (e) { if (e instanceof ComposioFileUploadPathNotAllowedError) { /* add the resolved dir from e.meta.resolved to fileUploadDirs */ } throw e; } Prevention
- Use realpath-resolved absolute paths in fileUploadDirs
- Place uploadable files in a dedicated allowlisted directory
- Remember symlinks are resolved before the allowlist check
When it happens
Trigger: fileUploadDirs is non-empty, the file exists, but it lives outside every allowlisted directory — including cases where a symlink resolves outside the allowlisted dir, or the allowlist entry doesn't match the realpath.
Common situations: Allowlist configured with a path that differs from where files actually land (relative vs absolute, symlinked tmp dirs like /var -> /private/var on macOS, Docker volume mounts); overly narrow allowlist.
Related errors
- Refusing to auto-upload
- Refusing to auto-upload
- Refusing to auto-upload
- Refusing to auto-upload
- Refusing to fetch a malformed URL
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/76f1a0529e4c9692.
Report an issue: GitHub.
Appendix: source
Thrown at ts/packages/core/src/utils/uploadDirAllowlist.node.ts:167
`Resolved to: ${real}`,
'',
'Automatic file upload during tool execution is locked down by default',
'to prevent a prompt-injected tool from exfiltrating server files',
'(source code, .env, SSH keys, etc.).',
buildHelpFooter(allowlist),
].join('\n'),
{ meta: { attempted, resolved: real, allowlist } }
);
}
for (const dir of allowlist) {
const realDir = tryRealpath(dir) ?? path.resolve(dir);
if (isInsideDir(real, realDir)) {
return;
}
}
throw new ComposioFileUploadPathNotAllowedError(
[
`Refusing to auto-upload "${attempted}": resolved path is not inside any`,
'directory in the configured `fileUploadDirs` allowlist.',
'',
`Path attempted: ${attempted}`,
`Resolved to: ${real}`,
buildHelpFooter(allowlist),
].join('\n'),
{ meta: { attempted, resolved: real, allowlist } }
);
}
View on GitHub (pinned to 64b1b85502)