发布

  • fix(cli): enforce sensitive-file upload denylist (GHSA-hp3h-89pf-5q58) (#3763)

    frostbyte_neo 发布于 2026-07-06 20:30:40 +00:00

    This PR:

    • fixes #3746 / GHSA-hp3h-89pf-5q58 — the CLI's tool file-upload path
      bypassed the sensitive-file denylist
    • root cause: the denylist was enforced at the caller layer, so
      @composio/cli's duplicate upload path (readFileFromDisk) read and
      uploaded any local path a tool argument pointed at — ~/.ssh/id_rsa,
      ~/.aws/credentials, .env, etc. — enabling credential exfiltration
      via composio execute / composio run (incl. LLM-driven agents hit by
      prompt injection)
    • unified fix: one canonical guard, exported from @composio/core
      and enforced at the read primitive in every SDK
    • core: the guard now routes fs/path access through the internal
      #platform abstraction (adds a realpathSync method), so it carries
      no static node:* imports and is exported from the package root:
      assertSafeFileUploadPath, isBlockedSensitiveFileUploadPath,
      BUILTIN_FILE_UPLOAD_PATH_DENY_SEGMENTS
    • cli: readFileFromDisk calls the shared assertSafeFileUploadPath
      before fs.readFile; URLs and File objects are unaffected (matches
      core)
    • python: already routes all uploads through the guarded
      FileUploadable.from_path — no functional change; adds regression tests
      for parity
    • supersedes #3755, which exported the then-node-only guard from core's
      main index.ts and would have injected node:fs into the shared
      dist/index.mjs (the workerd/edge-light entry), likely breaking
      Cloudflare Workers / Vercel Edge
    • changesets: @composio/core minor (new public exports),
      @composio/cli patch (security fix)

    Verification

    • core: full suite passes (997), incl. new root-export +
      realpath-symlink cases
    • edge bundle stays clean: built dist/index.mjs has no static
      node:* imports and reaches the platform only via #platform
    • cli: new regression test drives the real uploadToolInputFiles → readFileFromDisk → guard chain — ~/.ssh/id_rsa and .env throw
      ComposioSensitiveFilePathBlockedError before any createPresignedURL
      call; a normal file still uploads
    • python: test_files.py + sensitive-path suite pass (145), incl. 3 new
      from_path guard tests
    • tsgo typecheck + eslint clean for core and cli
    下载附件