Skip to content

Azure Blob: image/file download fails on private containers (400 Failed to download image) #13340

Open

Description

@anthonyguillaume

What happened

With fileStrategy: azure_blob and a storage account where anonymous public blob access is disabled at the account level, uploading an image to a vision-capable model fails:

400 Failed to download image from https://<account>.blob.core.windows.net/<container>/images/<userId>/<file>.webp

File preview/download from "My Files" fails the same way.

Root cause

For azure_blob/s3 sources, encodeAndFormat (api/server/services/Files/images/encode.js) downloads the blob server-side and base64-encodes it (the blob URL is never sent to the model). For Azure that download goes through getAzureFileStream (api/server/services/Files/Azure/crud.js), which makes an unauthenticated request:

async function getAzureFileStream(_req, fileURL) {
  const response = await axios({ method: 'get', url: fileURL, responseType: 'stream' });
  return response.data;
}

On a private container this returns 403, or 409 PublicAccessNotPermitted when the account disallows public access entirely. By contrast, S3's equivalent getS3FileStream uses the authenticated SDK (GetObjectCommand), so S3 works with private buckets — Azure is the inconsistent one here.

Steps to reproduce

  1. Azure Storage account with "Allow Blob anonymous access" disabled (the default for secured accounts).
  2. fileStrategy: azure_blob, AZURE_STORAGE_PUBLIC_ACCESS=false.
  3. Upload an image and send it to a vision-capable model → 400 Failed to download image.
  4. (Same root cause: downloading/previewing any uploaded file from "My Files".)

file_search/RAG over documents is unaffected, because the file is embedded at upload time from the local temp file, not re-fetched from the blob.

Expected behavior

Private Azure Blob containers should work, the same way S3 private buckets do.

Proposed fix

PR #13245 ("Azure Blob Storage URL Signing and Refresh Support") addresses this comprehensively via SAS URL signing, and is the preferred direction since it also covers cases where the blob URL is consumed directly by the client.

A minimal alternative (or complement) for the server-side download path is to make getAzureFileStream download through the authenticated SDK client, mirroring getS3FileStream:

async function getAzureFileStream(_req, fileURL) {
  try {
    const containerClient = await getAzureContainerClient(AZURE_CONTAINER_NAME);
    const rawPath = fileURL.split(`${AZURE_CONTAINER_NAME}/`)[1];
    if (!rawPath) {
      throw new Error('Blob path could not be derived from the file URL');
    }
    const blobPath = decodeURIComponent(rawPath.split('?')[0]);
    const blockBlobClient = containerClient.getBlockBlobClient(blobPath);
    const downloadResponse = await blockBlobClient.download();
    return downloadResponse.readableStreamBody;
  } catch (error) {
    logger.error('[getAzureFileStream] Error getting blob stream:', error);
    throw error;
  }
}

This keeps blobs fully private (nothing exposed to the model or anonymously) and works whether or not the container is public, since authenticated access is a superset.

Environment

  • LibreChat v0.7.9 (bug also present on main)
  • File storage: Azure Blob (azure_blob), connection-string auth
  • Storage account: anonymous public blob access disabled

Activity

  1. rahepler2 commented on May 30, 2026

    @rahepler2

    I just added a PR to address this. WOuld love your feedback on it: #13411

  2. JorgeCosta87 commented on Jun 1, 2026

    @JorgeCosta87
    Contributor

    A fix is in flight via #13411 (authenticated SDK + proxy) and #13245 (SAS signing). See the breakdown in #13411 — the two approaches are complementary: SAS-direct for zero-bandwidth client fetches, authenticated SDK + proxy for a no-bearer-token / Storage Blob Data Reader-only deployment. The shared server-side getAzureFileStream change (unauthenticated axios.get → authenticated SDK) is what closes the vision + preview/download path this issue describes.

  3. added a commit that references this issue on Jun 1, 2026
    952cae7
  4. added
    🗺️ File Storagecodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)
    🗺️ Server Corecodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)
    🗺️ Platform Securitycodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)
    🗺️ Core Infra & Seccodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)
    on Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐛 bugSomething isn't working🗺️ Core Infra & Seccodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)🗺️ File Storagecodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)🗺️ Platform Securitycodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)🗺️ Server Corecodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions