[Storage] Canonicalize backslashes in blob names when generating a blob SAS - #48697
Open
om singhal (Om-singhaI) wants to merge 1 commit into
Open
[Storage] Canonicalize backslashes in blob names when generating a blob SAS#48697om singhal (Om-singhaI) wants to merge 1 commit into
om singhal (Om-singhaI) wants to merge 1 commit into
Conversation
…a blob SAS The service treats a backslash in a blob name as a forward slash when it validates a SAS signature, but generate_blob_sas signed the blob name verbatim. Any SAS generated for a blob name containing a backslash was therefore rejected with a 403. Normalize backslashes to forward slashes when building the signed resource path, matching the Go and .NET SDKs. Directory names are signed as given, as in the Go SDK. The blob name used in the request URL is unchanged. Adds a standalone unit test that checks the canonicalized resource line through the existing sts_hook parameter, and a CHANGELOG entry. Fixes Azure#48690
om singhal (Om-singhaI)
requested review from
anjaliratnam-msft,
Jacob Lauzon (jalauzon-msft),
vincenttran-msft and
Peter Wu (weirongw23-msft)
as code owners
August 22, 2026 20:10
Contributor
|
Thank you for your contribution om singhal (@Om-singhaI)! We will review the pull request and get back to you soon. |
|
Azure Pipelines: Successfully started running 1 pipeline(s). 7 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes blob SAS authentication for blob names containing backslashes by matching Azure Storage’s canonicalization behavior.
Changes:
- Normalizes backslashes only for non-directory SAS resource paths.
- Adds focused tests for signatures, directory behavior, and URL encoding.
- Documents the fix in the changelog.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
_shared_access_signature.py |
Canonicalizes blob names during SAS signing. |
test_shared_access_signature.py |
Tests blob and directory SAS behavior. |
CHANGELOG.md |
Records the bug fix. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #48690
generate_blob_sasinserted the blob name verbatim into the canonicalized resource of the string to sign (resource_path = container_name + "/" + blob_nameinsdk/storage/azure-storage-blob/azure/storage/blob/_shared_access_signature.py). The Azure Storage service canonicalizes a backslash (\) in a blob name to a forward slash (/) before it validates the signature, so a SAS generated for any blob name containing a backslash never matched and the service rejected it with a 403. The reporter reproduced this against Azurite.This change normalizes backslashes to forward slashes in the blob name when building the signed resource path, so the computed signature matches what the service computes. It mirrors the sibling SDKs:
sdk/storage/azblob/sas/service.go,getCanonicalName(lines 336 to 345): appendsstrings.ReplaceAll(blobName, "\\", "/")at line 341 and leavesdirectoryNameuntouched.sdk/storage/Azure.Storage.Blobs/src/Sas/BlobSasBuilder.cs,GetCanonicalName(lines 591 to 594):blobName.Replace("\\", "/").Scope follows the Go implementation exactly: only the blob name is normalized, and only when
is_directoryis not set. Directory names are signed as given. The container name is not touched. The blob name used in the request URL is not changed (it is still percent encoded as%5C), only the signed resource line is. Sinceazure-storage-file-datalakewrapsgenerate_blob_sas, the fix propagates there as well.A note on scope: the issue currently carries the default
questionlabel, but the behavior is a defect. Non HNS accounts canonicalize a backslash the same way, which is why the Go and .NET SDKs apply this normalization unconditionally for blob names.Before (string to sign, canonicalized resource line, for
blob_name="dir\\file"):After:
Testing
Added
sdk/storage/azure-storage-blob/tests/test_shared_access_signature.py, a standalone unit test module that uses the existingsts_hookparameter ofgenerate_blob_sasto capture the string to sign. It asserts that:/in place of the backslash, the token'ssris stillb, the token is identical to the one generated for the equivalent forward slash name, and the URL path built byBlobClientstill carries the original%5Cencoded name;is_directory=Truethe directory name is signed as given andsrisd.The new test fails on the parent commit (1 failed, 1 passed) and passes with this change (2 passed). Ran
blackwitheng/black-pyproject.tomlon the changed files (no changes) andpylintwith the repo rc files (no new findings attributable to this change).All SDK Contribution checklist:
General Guidelines and Best Practices
Testing Guidelines