{"record":{"id":"bd9f8baccd7e5890","repo":"ComposioHQ/composio","slug":"refusing-to-upload-reason-remediation","errorCode":null,"errorMessage":"Refusing to upload: ${reason}. ${remediation}","messagePattern":"Refusing to upload: (.+?)\\. (.+?)","errorType":"exception","errorClass":"ComposioSensitiveFilePathBlockedError","httpStatus":null,"severity":"error","filePath":"ts/packages/core/src/utils/sensitiveFileUploadPaths.ts","lineNumber":144,"sourceCode":" * that exposes `sensitiveFileUploadProtection`. Callers without such an opt-out\n * (e.g. `@composio/cli`) should pass their own `remediation` so the message does\n * not advertise an option the caller cannot honor.\n */\nconst DEFAULT_REMEDIATION =\n  `To upload from this path anyway, set sensitiveFileUploadProtection: false on Composio ` +\n  `(not recommended) or use a copy outside sensitive locations.`;\n\n/**\n * @throws {ComposioSensitiveFilePathBlockedError} if the path is not allowed\n */\nexport function assertSafeFileUploadPath(\n  filePath: string,\n  options?: { additionalDenySegments?: string[]; remediation?: string }\n): void {\n  const reason = getSensitiveFileUploadPathBlockReason(filePath, options?.additionalDenySegments);\n  if (reason) {\n    const remediation = options?.remediation ?? DEFAULT_REMEDIATION;\n    throw new ComposioSensitiveFilePathBlockedError(\n      `Refusing to upload: ${reason}. ${remediation}`,\n      {\n        meta: { filePath, reason },\n      }\n    );\n  }\n}\n","sourceCodeStart":126,"sourceCodeEnd":152,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/core/src/utils/sensitiveFileUploadPaths.ts#L126-L152","documentation":"Before uploading a local file (e.g. readFileFromDisk / getFileDataAfterUploadingToS3), the SDK inspects the path and refuses to read sensitive locations (.env, SSH keys, cloud credentials, dotfiles, etc.). This ComposioSensitiveFilePathBlockedError lists the reason and a remediation hint.","triggerScenarios":"Passing a file path that contains a denied segment — .env, id_rsa, .aws/credentials, .git config, service account keys, or a path matching the sensitive-path rules (optionally extended by additionalDenySegments).","commonSituations":"An LLM agent tries to 'upload context' and points at .env or ~/.ssh/id_rsa; tools that default to home-directory dotfiles; CI trying to upload a directory containing credential files.","solutions":["Point the upload at the actual non-sensitive file you intend to share","If the file legitimately lives under a flagged-looking name, copy it to a neutral path first and upload that copy","Never work around the guard by copying credentials — move secrets to environment variables instead","Pass a custom remediation/additionalDenySegments only if you wrap the API yourself"],"exampleFix":"// before\nawait upload.readFileFromDisk('/myapp/.env');\n\n// after\n// .env is intentionally blocked; upload a sanitized config sample instead\nawait upload.readFileFromDisk('/myapp/config.example.json');","handlingStrategy":"validation","validationCode":"const SENSITIVE = [/(^|\\/)\\.env(/|$)/, /(\\.ssh|\\.aws|\\.gnupg)/, /id_rsa/, /credentials/i];\nconst looksSensitive = (p: string) => SENSITIVE.some(rx => rx.test(p));\nif (looksSensitive(path)) throw new Error('Refusing local sensitive path');","typeGuard":"null","tryCatchPattern":"try {\n  await upload.readFileFromDisk(path);\n} catch (e) {\n  if (e instanceof ComposioSensitiveFilePathBlockedError) {\n    // choose a different, non-sensitive file; never bypass\n  }\n}","preventionTips":["Constrain agent-selectable upload paths to an explicit allowlist directory","Keep secrets in env vars, not files an agent can reach","Treat this block as a security control, not a bug to work around"],"tags":["security","file-upload","path-validation","secrets"],"backgroundTag":"sensitive-file-access-blocked","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}