Summary
When communicating with an S3-compatible provider that returns a whitespace-only LocationConstraint, minio-go caches the whitespace verbatim. That cached value is later used as the region component of the SigV4 credential scope, producing an invalid Authorization header containing embedded newlines.
Trimming the LocationConstraint before caching resolves the issue.
Environment
- minio-go: v7.2.1
- Go: 1.26
- Tested against a third-party S3-compatible provider.
Minimal reproducer
client, err := minio.New(endpoint, &minio.Options{
Creds: credentials.NewStaticV4(accessKey, secretKey, ""),
Secure: true,
})
client.TraceOn(os.Stdout)
_, err = client.FPutObject(
context.Background(),
bucket,
"test.txt",
"test.txt",
minio.PutObjectOptions{},
)
(Full reproducer attached.)
Investigation
I instrumented:
bucket-cache.go
request-signature-v4.go
The only functional change was:
location := strings.TrimSpace(locationConstraint)
Everything else was debug logging.
Observed behavior (before patch)
The bucket location response is decoded as:
LocationConstraint: "\n \n \n \n \n \n \n \n\n"
That value is cached and later becomes the region portion of the SigV4 credential scope.
The generated credential becomes conceptually:
ACCESSKEY/DATE/<whitespace>/s3/aws4_request
resulting in an Authorization header containing embedded newlines.
Go then rejects the request before it is sent with:
net/http: invalid header field value for "Authorization"
Expected behavior
Whitespace surrounding LocationConstraint should not become part of the cached bucket location.
A whitespace-only value should behave the same as an empty value and ultimately resolve to the default region (us-east-1).
Proposed fix
- location := locationConstraint
+ location := strings.TrimSpace(locationConstraint)
if location == "" {
location = "us-east-1"
}
Result after patch
With only the above change:
- identical credentials
- identical endpoint
- identical bucket
- identical application
the upload succeeds successfully.
Notes
I believe the S3 provider is also behaving poorly by returning a whitespace-only LocationConstraint rather than an empty element or a region value.
However, trimming the decoded value makes minio-go more robust and prevents malformed Authorization headers from being generated.
debug.output.txt
diff.txt
main.go.txt
patched.output.txt
Summary
When communicating with an S3-compatible provider that returns a whitespace-only
LocationConstraint,minio-gocaches the whitespace verbatim. That cached value is later used as the region component of the SigV4 credential scope, producing an invalidAuthorizationheader containing embedded newlines.Trimming the
LocationConstraintbefore caching resolves the issue.Environment
Minimal reproducer
(Full reproducer attached.)
Investigation
I instrumented:
bucket-cache.gorequest-signature-v4.goThe only functional change was:
Everything else was debug logging.
Observed behavior (before patch)
The bucket location response is decoded as:
That value is cached and later becomes the region portion of the SigV4 credential scope.
The generated credential becomes conceptually:
resulting in an
Authorizationheader containing embedded newlines.Go then rejects the request before it is sent with:
Expected behavior
Whitespace surrounding
LocationConstraintshould not become part of the cached bucket location.A whitespace-only value should behave the same as an empty value and ultimately resolve to the default region (
us-east-1).Proposed fix
Result after patch
With only the above change:
the upload succeeds successfully.
Notes
I believe the S3 provider is also behaving poorly by returning a whitespace-only
LocationConstraintrather than an empty element or a region value.However, trimming the decoded value makes
minio-gomore robust and prevents malformedAuthorizationheaders from being generated.debug.output.txt
diff.txt
main.go.txt
patched.output.txt