From a2ff3c2ecde8e71a5442340a82053273737acbaa Mon Sep 17 00:00:00 2001 From: Denis Babchuk Date: Sat, 7 Nov 2026 11:43:31 +0300 Subject: [PATCH] fix(api): keep GetObjectAttributes server errors and check s3:ListBucket on the bucket Signed-off-by: Denis Babchuk --- cmd/auth-handler.go | 13 +++++++++++++ cmd/object-handlers.go | 13 ++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/cmd/auth-handler.go b/cmd/auth-handler.go index a20a74505..700126b47 100644 --- a/cmd/auth-handler.go +++ b/cmd/auth-handler.go @@ -425,6 +425,19 @@ func authorizeRequest(ctx context.Context, r *http.Request, action policy.Action return authorizeRequestWithExistingTags(ctx, r, action, "") } +// authorizeBucketRequest authorizes a bucket action, such as s3:ListBucket, +// on the bucket of a request made for one of its objects. +func authorizeBucketRequest(ctx context.Context, r *http.Request, action policy.Action) APIErrorCode { + reqInfo := logger.GetReqInfo(ctx) + if reqInfo == nil { + return ErrAccessDenied + } + objectName := reqInfo.ObjectName + reqInfo.ObjectName = "" + defer func() { reqInfo.ObjectName = objectName }() + return authorizeRequest(ctx, r, action) +} + func deleteObjectAction(versionID string) policy.Action { if versionID != "" { return policy.DeleteObjectVersionAction diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index e77fcb4f2..841d3578d 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -629,12 +629,15 @@ func (api objectAPIHandlers) getObjectAttributesHandler(ctx context.Context, obj objInfo, err := objectAPI.GetObjectInfo(ctx, bucket, object, opts) if err != nil { - s3Error = authorizeRequest(ctx, r, policy.ListBucketAction) - if s3Error == ErrNone { - writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) - return + // As with S3, a caller without s3:ListBucket on the bucket gets + // AccessDenied in place of NoSuchKey. A server error, such as lost + // read quorum, tells nothing about the object and reaches the caller, + // who may read the object, as it is. + apiErr := toAPIError(ctx, err) + if apiErr.HTTPStatusCode < http.StatusInternalServerError && authorizeBucketRequest(ctx, r, policy.ListBucketAction) != ErrNone { + apiErr = errorCodes.ToAPIErr(ErrAccessDenied) } - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) + writeErrorResponse(ctx, w, apiErr, r.URL) return }