[Windows Desktop] Connector file_uri cannot be materialized into Codex local workspace

Open 💬 0 comments Opened Jul 31, 2026 by Lorre2904

Summary

On Codex Windows Desktop, a connected app can return a large non-native file as an opaque, user-scoped file_uri, but the same Codex task has no supported bridge that accepts that reference and returns a workspace-readable local path.

This blocks otherwise authorized local workflows such as validating archive signatures, checking exact byte size and checksums, extracting structured assets, and running existing local parsers.

Environment

  • Windows Desktop
  • codex-cli 0.145.0
  • Connected Google Drive app
  • Authorized non-native binary file larger than 10 MB

Minimal reproduction

  1. In a Codex task with access to a connected Drive file, inspect the exposed connector schema.
  2. Fetch the authorized non-native file with raw streaming enabled and inline bytes disabled.
  3. Observe that the connector returns an opaque, user-scoped file_uri.
  4. Inspect the schemas exposed to the same task for a supported operation that accepts that connector reference and returns a local, mounted, artifact, or workspace-readable path.
  5. Observe that no such operation is exposed. Local terminal and runtime tools can only open files that already have local paths.

Illustrative expected chain:

reference = drive.fetch(
  url="<REDACTED_DRIVE_FILE_ID>",
  download_raw_file=true,
  include_base64=false
).file_uri

local = files.materialize(
  file_uri=reference,
  destination="<AUTHORIZED_WORKSPACE>/input.bin",
  overwrite=false
)

assert local.local_path is inside "<AUTHORIZED_WORKSPACE>"
assert file_size(local.local_path) == local.size_bytes
assert sha256(local.local_path) == local.sha256

The files.materialize call above is illustrative; it is not exposed in the affected session.

Expected behavior

Codex should expose a supported connector-file-to-workspace materialization operation that:

  • accepts the exact structured opaque reference returned by a connector;
  • atomically writes the file into an explicitly authorized workspace or product-managed artifact area;
  • returns a canonical local path, MIME type, exact size, and SHA-256;
  • supports bounded cancellation, deterministic cleanup, and safe retry behavior;
  • requires no credentials, base64 transfer, hidden mounts, security-setting changes, or guessed URI conversion.

Actual behavior

The workflow stops at the connector reference:

  • the Drive connector can produce a user-scoped file_uri;
  • connector-reference consumers that are exposed perform writes to external services rather than returning a local path;
  • terminal, Python, and Node tools can work with existing local paths but do not accept a connector reference;
  • no qualifying connector-reference-to-local-path bridge is exposed.

Result: the source is authorized and represented by a connector reference, but it cannot be consumed by local tools in the same task.

Layers already ruled out

  • The source object identity and non-native MIME type were verified through metadata-only access.
  • The connector producer contract is present and explicitly supports a streamed file_uri without inline bytes.
  • Existing external-service consumers do not solve local materialization.
  • The local tools are available and can read normal workspace files; the missing contract is the handoff into the workspace.
  • No guessed URI-to-path conversion, source modification, re-upload, browser workaround, or security-policy change was used.

Nature of the returned object

The current connector result is a Sediment-backed, user-scoped file_uri: an opaque reference managed by the runtime. It is neither documented nor safe to interpret as a Windows filesystem path. The model should pass the structured reference to a supported consumer rather than extract, fabricate, or decode an internal URI.

Why base64 is not a scalable fix

Inline base64 would expand the payload, consume model/tool context, increase the chance of truncation, make retries expensive, and create unnecessary exposure in arguments, logs, and transcripts. It also bypasses the useful authorization and lifecycle properties of the opaque connector reference. Large binary handoff should remain streamed and out of model context.

Suggested materialization contract

Illustrative schema:

files.materialize({
  file_uri: ConnectorFileReference,
  destination: WorkspaceRelativePath,
  overwrite: false,
  idempotency_key: string | null
}) -> {
  local_path: AbsoluteWorkspacePath,
  mime_type: string | null,
  size_bytes: integer,
  sha256: string,
  source_reference_type: string,
  cleanup_token: string | null
}

Suggested guarantees:

  1. Accept the structured reference exactly as returned by a connector.
  2. Normalize the destination and enforce workspace containment after symlink resolution.
  3. Stream to a private temporary file, validate completion, then rename atomically.
  4. Refuse overwrite by default.
  5. Return exact size and SHA-256 calculated over the materialized bytes.
  6. Preserve connector authorization and tenancy boundaries.
  7. Define idempotent retry or destination-conflict semantics.
  8. Remove only temporary files created by that call after cancellation or failure.

Useful typed errors would include:

  • REFERENCE_EXPIRED
  • REFERENCE_NOT_AUTHORIZED
  • UNSUPPORTED_REFERENCE_TYPE
  • DESTINATION_OUTSIDE_WORKSPACE
  • DESTINATION_EXISTS
  • SOURCE_CHANGED
  • SIZE_LIMIT_EXCEEDED
  • TRANSFER_INTERRUPTED
  • INTEGRITY_CHECK_FAILED
  • LOCAL_WRITE_FAILED

Security requirements

  • Do not accept arbitrary provider URLs as an authorization bypass.
  • Do not expose connector credentials, signed URLs, internal storage paths, tenant identifiers, usernames, or source titles.
  • Do not put binary or base64 payloads into model-visible calls or logs.
  • Require no registry, policy, service, scheduled-task, ACL, UAC, or credential changes.
  • Keep all final destinations inside the authorized workspace or a product-managed artifact area.

Suggested acceptance tests

  1. Materialize an authorized non-native connector file larger than 10 MB.
  2. Confirm that terminal and runtime tools can read the returned path.
  3. Verify exact size, SHA-256, and a known file signature.
  4. Repeat safely without duplicate or partial files.
  5. Interrupt transfer and confirm that neither the final destination nor an orphan .part file remains.
  6. Reject out-of-workspace destinations and malformed, expired, or cross-user references.
  7. Confirm that the source object and its metadata are not modified.
  8. Confirm that no base64, credentials, signed URLs, or sensitive identifiers appear in calls or logs.

Attachment note

A redacted evidence ZIP containing the minimal reproduction, product request, schema matrix, evidence index, and a small schema-search log is available. It should be uploaded only during a separately authorized final-submission step; no attachment is uploaded as part of this staging task.

View original on GitHub ↗