Skip to content

[azure-storage-blob] Regression in 12.30.0: BlobClient drops the path from account_url #48276

Description

@chuckz1321
  • Package Name: azure-storage-blob
  • Package Version: 12.30.0 (regression from 12.29.0)
  • Operating System: Windows 11 10.0.26200 (controlled reproduction)
  • Python Version: 3.14.3 (controlled reproduction)

Describe the bug

BlobClient 12.30.0 drops the existing path component from an account_url when the host matches a standard Azure Storage endpoint. Version 12.29.0 preserved that path.

This changes the behavior of a directory-scoped SAS usage pattern where a full directory SAS URL is passed as account_url together with container_name=".". With 12.29.0, the generated URL remains under the signed directory and the upload succeeds. With 12.30.0, the signed directory path is removed, the request resolves to the account root, and Azure Storage returns HTTP 403 AuthenticationFailed / Signature did not match.

We recognize that this usage does not strictly follow the documented constructor contract: account_url is documented as the storage account URI. However, upgrading between stable package versions silently changes the URL and produces a remote authentication error rather than a clear client-side validation error. The change is also not identified as breaking in the changelog.

To Reproduce

Prerequisite: an HNS-enabled storage account and a valid directory-scoped SAS URL (sr=d, sdd=1) for <container>/<directory>. Do not include a real SAS in logs or issue text.

import os
from urllib.parse import urlsplit, urlunsplit

from azure.storage.blob import BlobClient


def without_query(url: str) -> str:
    parsed = urlsplit(url)
    return urlunsplit((parsed.scheme, parsed.netloc, parsed.path, "", ""))


directory_sas_url = os.environ["DIRECTORY_SAS_URL"]

client = BlobClient(
    account_url=directory_sas_url,
    container_name=".",
    blob_name="probe.txt",
    api_version="2024-11-04",
)

print(without_query(client.url))
client.upload_blob(b"test", overwrite=False)

Run the same script with the following package versions while keeping the transitive dependencies unchanged:

  • azure-storage-blob==12.29.0
  • azure-storage-blob==12.30.0
  • azure-core==1.41.0
  • requests==2.34.2

Observed result with 12.29.0:

https://<account>.blob.core.windows.net/<container>/<directory>/./probe.txt
Upload succeeds.

Observed result with 12.30.0:

https://<account>.blob.core.windows.net/./probe.txt
HTTP 403 AuthenticationFailed: Signature did not match.

As a control, using the same directory SAS with the account URL, actual container name, and <directory>/probe.txt as the blob name succeeds on 12.30.0.

Expected behavior

Please confirm whether dropping the path is intentional.

  • If it is not intentional, 12.30.x should preserve the path as 12.29.0 did.
  • If resource-level URLs passed as account_url are intentionally unsupported, the constructor should preferably fail fast with a clear ValueError, and the behavior change should be documented. It should not silently redirect the request to a different resource path and surface only as a Storage authentication failure.

Additional context

The behavior appears to have changed in the endpoint construction added for IPv6/dual-stack support:

  • In 12.29.0, primary_hostname included parsed_url.path:

    primary_hostname = (parsed_url.netloc + parsed_url.path).rstrip("/")
  • In 12.30.0, recognized Storage endpoints are passed to _construct_endpoints(parsed_url.netloc, account[0]), which constructs the endpoint from netloc only.

Relevant change:

The 12.30.0b1 changelog mentions support for -ipv6 and -dualstack account URLs, but does not mention removal of an existing URL path or a breaking behavior change.

The issue can also be observed without sending a request: inspecting client.url with a placeholder standard Blob endpoint shows that 12.29.0 preserves /container/directory, while 12.30.0 removes it. This indicates a client-side URL-construction change rather than a Storage service behavior difference.

Metadata

Metadata

Labels

ClientThis issue points to a problem in the data-plane of the library.Service AttentionWorkflow: This issue is responsible by Azure service team.StorageStorage Service (Queues, Blobs, Files)customer-reportedIssues that are reported by GitHub users external to the Azure organization.needs-team-attentionWorkflow: This issue needs attention from Azure service team or SDK teamquestionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions