Skip to content

fix: enforce SignedHeaders validation for SigV4 requests#2158

Open
niksis02 wants to merge 1 commit into
mainfrom
sis/presigned-urls-signed-headers
Open

fix: enforce SignedHeaders validation for SigV4 requests#2158
niksis02 wants to merge 1 commit into
mainfrom
sis/presigned-urls-signed-headers

Conversation

@niksis02
Copy link
Copy Markdown
Contributor

Validate incoming request headers against the client-provided SignedHeaders for both Authorization-header SigV4 requests and presigned URLs.

During request reconstruction, only signed headers and explicitly ignored headers are copied into the generated request used for signature verification. If an incoming header is present, is required to be signed, and is missing from SignedHeaders, return a new AccessDenied response with a HeadersNotSigned field.

Previously, a client could sign a request without an S3 control header and then add that header after signing. For example, a presigned PUT URL could be generated with only host signed, then the actual request could include an unsigned X-Amz-Tagging or X-Amz-Copy-Source header. Because the verifier reconstructed the request only from SignedHeaders, that extra header was omitted from signature calculation and could pass authentication even though it changed the request semantics. This is now rejected with AccessDenied.

Update SigV4 header rules so all X-Amz-* headers are treated as required signed headers to match the S3 behavior.

Expose v4 helper methods for checking required and ignored headers, and update canonical header signing so ignored headers can still be included when a client explicitly lists them in SignedHeaders, while Authorization remains excluded from signature calculation.

@niksis02 niksis02 self-assigned this May 29, 2026
Validate required signed headers for both Authorization-header SigV4 requests and presigned URLs. The required signed header set is now `host` plus every incoming header with the `x-amz-` prefix.

During request reconstruction, signed headers and explicitly ignored headers are copied into the generated request used for signature verification. If an incoming `x-amz-*` header is present but missing from the client-provided `SignedHeaders`, return `AccessDenied` with a `HeadersNotSigned` field. The `host` header remains part of the canonical request and signed header calculation.

Previously, a client could sign a request without an S3 control header and then add that header after signing. For example, a presigned `PUT` URL could be generated with only `host` signed, then the actual request could include an unsigned `X-Amz-Tagging` or `X-Amz-Copy-Source` header. Because the verifier reconstructed the request only from `SignedHeaders`, that extra header was omitted from signature calculation and could pass authentication even though it changed the request semantics. This is now rejected with `AccessDenied`.

Expose v4 helper methods for checking required and ignored headers, and update canonical header signing so ignored headers can still be included when a client explicitly lists them in `SignedHeaders`, while `Authorization` remains excluded from signature calculation.
@niksis02 niksis02 force-pushed the sis/presigned-urls-signed-headers branch from 891c53b to 5774702 Compare May 30, 2026 17:17
@niksis02 niksis02 requested a review from benmcclelland May 30, 2026 17:28
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.

1 participant