Container-scoped Blob Batch runs subrequests on another container whose name starts with the scope container's name

Abierto Apto para principiantes
#2,884 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@compiler-segfault ya está trabajando en esto.

Desde el 6/11/2026.

  • #2891 de @compiler-segfault — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
82/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
azure, typescript
Área
backend

Línea de trabajo

Empieza por la comprobación de prefijo en parseSubRequests en src/blob/handlers/BlobBatchHandler.ts (alrededor de la línea 405). submitBatch en src/blob/handlers/ContainerHandler.ts pasa la ruta de la solicitud por lotes como ese prefijo. Primero confirma que un prefijo de ruta sin barra final hace que /devstoreaccount1/logs-archive/b1 coincida con /devstoreaccount1/logs. Está terminado cuando una subsolicitud para un contenedor cuyo nombre extiende el nombre del ámbito se rechaza con un 400 InvalidInput y una prueba de regresión en tests/blob/apis/blobbatch.test.ts cubre ese caso.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Which service(blob, file, queue, table) does this issue concern?

Blob

Which version of the Azurite was used?

3.37.0 (also seen on 3.29.0)

Where do you get Azurite? (npm, DockerHub, NuGet, Visual Studio Code Extension)

Docker image mcr.microsoft.com/azure-storage/azurite:3.37.0 (same digest as latest)

What's the Node.js version?

v22.23.2 (the one in the image)

What problem was encountered?

A Blob Batch scoped to a container (POST /devstoreaccount1/logs?restype=container&comp=batch)
should refuse every subrequest that targets another container. Azurite refuses a subrequest for
audit/b1 (sub-status 400 InvalidInput), but it runs a subrequest for logs-archive/b1: the
sub-status is 202 and the blob in logs-archive is deleted. Any container whose name starts
with the scope container's name is treated as the same container.

Blob Batch, Scope all subrequests to a specific container:

Beginning with REST version 2020-04-08, the Blob Batch API supports scoping subrequests to a
specified container. When the request URI includes the container name and the restype=container
parameter, then each subrequest must apply to the same container. If the container name specified
for a subrequest doesn't match the container name provided in URI, the service returns error code
400 (Bad Request).

The URI parameters
table says the same for restype: "Any subrequests must be scoped to the same container."

Expected: the logs-archive/b1 subrequest fails as the audit/b1 one does, and logs-archive
still holds b1.

Steps to reproduce the issue?
docker run -d -p 10000:10000 mcr.microsoft.com/azure-storage/azurite:3.37.0 azurite-blob --blobHost 0.0.0.0
npm install @azure/storage-blob

repro.mjs (the same calls as the test "SubmitBatch within container scope - batch deleting blob
in different container" in tests/blob/apis/blobbatch.test.ts, with container names that share a
prefix):

import { BlobServiceClient } from "@azure/storage-blob";

const service = BlobServiceClient.fromConnectionString("UseDevelopmentStorage=true");

const logs = service.getContainerClient("logs");
const archive = service.getContainerClient("logs-archive");
const audit = service.getContainerClient("audit");
for (const c of [logs, archive, audit]) await c.create();
await archive.getBlockBlobClient("b1").upload("data", 4);
await audit.getBlockBlobClient("b1").upload("data", 4);

// Blob Batch scoped to container "logs" (POST /devstoreaccount1/logs?restype=container&comp=batch)
const batch = logs.getBlobBatchClient();
for (const target of [archive, audit]) {
  const r = await batch.deleteBlobs([target.getBlobClient("b1").url], service.credential);
  console.log(`batch on logs, delete ${target.containerName}/b1: ` +
    `succeeded ${r.subResponsesSucceededCount}, failed ${r.subResponsesFailedCount}`);
}
for (const c of [archive, audit]) {
  const names = [];
  for await (const b of c.listBlobsFlat()) names.push(b.name);
  console.log(`blobs in ${c.containerName}:`, names);
}

node repro.mjs on 3.37.0:

batch on logs, delete logs-archive/b1: succeeded 1, failed 0
batch on logs, delete audit/b1: succeeded 0, failed 1
blobs in logs-archive: []
blobs in audit: [ 'b1' ]

On the wire the first batch is POST /devstoreaccount1/logs?restype=container&comp=batch with
the single subrequest DELETE /devstoreaccount1/logs-archive/b1 HTTP/1.1; the batch answers
202 and the subresponse is HTTP/1.1 202 Accepted. For audit the subresponse is
HTTP/1.1 400 One of the request inputs is not valid. with x-ms-error-code: InvalidInput.

Have you found a mitigation/solution?

Mitigation: do not rely on a container-scoped batch to stop subrequests for other containers.

Potential cause. BlobBatchHandler.parseSubRequests checks each subrequest path with
if (!requestPath.startsWith(subRequestPathPrefix))
(src/blob/handlers/BlobBatchHandler.ts:405 on main). ContainerHandler.submitBatch passes the
batch request's path as the prefix
(blobServiceCtx.request!.getPath()),
that is /devstoreaccount1/logs with no trailing /. So /devstoreaccount1/logs-archive/b1
passes the check. The existing test uses container<n> and containernew<n>, which do not share
a prefix, so it does not catch this.

Suggested fix. Compare against the prefix with a trailing /, for example
const prefix = subRequestPathPrefix.endsWith("/") ? subRequestPathPrefix : subRequestPathPrefix + "/";
and if (!requestPath.startsWith(prefix)), and add a test whose second container is the scope
container's name plus a suffix.

Lenguaje dominante
TypeScript
Estrellas
2.3k
Forks
400
Merge medio
4 d 9 h
PR fusionados (30 d)
23

Preparar el entorno

  • Incluye un Dockerfile o un archivo de Docker Compose
  • Tiene una plantilla de pull request
  • Sin guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de Azure/Azurite

Todos los issues de Azure/Azurite

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.