ComposioHQ/composio · error · ComposioFileUploadPathNotAllowedError

Refusing to auto-upload "${attempted}": resolved path is not

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).

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)

Solutions

  1. Add the file's actual directory (the 'Resolved to' path's parent) to fileUploadDirs
  2. Use absolute, realpath-resolved paths in the allowlist (fs.realpathSync) to defeat symlink mismatches
  3. Widen deliberately, e.g. add os.tmpdir() if tools write temp files there
  4. 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

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


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/76f1a0529e4c9692. Report an issue: GitHub.