Skip to content

Accept a blob SAS scoped to one blob version (sr=bv) - #2905

Open
Gavin Thompson (gavin-thompson-postman) wants to merge 1 commit into
Azure:mainfrom
gavin-thompson-postman:blob-version-sas
Open

Gavin Thompson (gavin-thompson-postman) wants to merge 1 commit into
Azure:mainfrom
gavin-thompson-postman:blob-version-sas

Conversation

@gavin-thompson-postman

Copy link
Copy Markdown

Azure Storage accepts a service SAS whose signed resource is one blob version (sr=bv). The SDKs generate one for a version client, e.g. blockBlobClient.withVersion(id).generateSasUrl(...), and it signs the version id in the field a snapshot SAS signs its snapshot time in.

Azurite's BlobSASAuthenticator skipped such a SAS as having an invalid signed resource type. So with blob versioning on (#2735), these failed with 403:

  • reading a previous version through a SAS (AuthorizationFailure);
  • using that SAS as the source of Put Blob From URL (CannotVerifyCopySource).

The same requests succeed against a real versioned storage account.

This accepts bv alongside b and bs:

  • its permissions are judged as a blob's;
  • the canonical resource includes the blob name;
  • the signed version is taken from the request's versionid, so a SAS for one version can't read another.

New tests in blockblob.versioning.test.ts:

  • read a previous version through a version SAS;
  • copy from it with Put Blob From URL;
  • refuse a version SAS used for a different version.

The first two fail without the change. The SAS and versioning suites pass (222 tests), and lint is clean.

Found while running S3Proxy's azureblob backend against Azurite with versioning on (gaul/s3proxy#1236). S3Proxy signs the copy source this way when an S3 copy names a source version.

Generated with Claude Code

Azure Storage accepts a service SAS whose signed resource is a blob
version, which the SDKs generate for a version client: sr=bv, with the
version id signed in the field a snapshot SAS signs its snapshot time
in.  Azurite's blob SAS authenticator skipped such a SAS as having an
invalid signed resource type, so reading a version through one, or
using one as the source of Put Blob From URL, failed with 403
AuthorizationFailure (CannotVerifyCopySource for the copy).

Accept bv alongside b and bs: judge its permissions as a blob's, sign
over the blob name, and take the signed version from the versionid the
request names, so a SAS for one version does not read another.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 12, 2026 16:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical version-SAS flaws leave user-delegation signatures unbound to the version, allow authorization to escape to the base blob, and check the wrong permission for version deletion.

3 open issues
What changed in this PR

This PR extends Azurite’s blob-versioning support to accept service SAS tokens scoped to a single version (sr=bv), enabling authenticated reads and Put Blob From URL copies of previous versions.

Changes:

  • Recognizes bv and incorporates the blob name and requested version into service SAS validation.
  • Adds tests for version-scoped reads, copies, and rejection of a different version.
  • Documents the user-visible behavior in the upcoming-release changelog.

Validation here was limited to code inspection; no builds or tests were run.

File Description
tests/​blob/​apis/​blockblob.versioning.test.ts Adds version-SAS read, copy, and cross-version rejection tests.
src/​blob/​authentication/​IBlobSASSignatureValues.ts Includes the blob name for bv in selected signature formats.
src/​blob/​authentication/​BlobSASResourceType.ts Defines the bv signed resource type.
src/​blob/​authentication/​BlobSASAuthenticator.ts Accepts bv, selects blob permissions, and extracts the signed version.
ChangeLog.md Announces version-scoped service SAS support.

Review effort: Balanced

Comment on lines +108 to +109
resource !== BlobSASResourceType.BlobSnapshot &&
resource !== BlobSASResourceType.BlobVersion
Comment on lines +394 to 395
resource === BlobSASResourceType.BlobVersion
? OPERATION_BLOB_SAS_BLOB_PERMISSIONS.get(operation)
Comment on lines +393 to 395
resource === BlobSASResourceType.Blob ||
resource === BlobSASResourceType.BlobVersion
? OPERATION_BLOB_SAS_BLOB_PERMISSIONS.get(operation)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants