fix: fixes the bucket/object tagging key/value name validation

Fixes #1579

S3 enforces a specific rule for validating bucket and object tag key/value names. This PR integrates the regexp pattern used by S3 for tag validation.
Official S3 documentation for tag validation rules: [AWS S3 Tag](https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_Tag.html)

There are two types of tagging inputs for buckets and objects:

1. **On existing buckets/objects** — used in the `PutObjectTagging` and `PutBucketTagging` actions, where tags are provided in the request body.
2. **On object creation** — used in the `PutObject`, `CreateMultipartUpload`, and `CopyObject` actions, where tags are provided in the request headers and must be URL-encoded.

This implementation ensures correct validation for both types of tag inputs.
This commit is contained in:
niksis02
2025-10-20 14:41:33 +04:00
parent 2bf4ccd244
commit ebf7a030cc
4 changed files with 165 additions and 20 deletions

View File

@@ -658,6 +658,11 @@ const (
TagLimitObject TagLimit = 10
)
// The tag key/value validation pattern comes from
// AWS S3 docs
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_Tag.html
var tagRule = regexp.MustCompile(`^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`)
// Parses and validates tagging
func ParseTagging(data []byte, limit TagLimit) (map[string]string, error) {
var tagging s3response.TaggingInput
@@ -682,18 +687,30 @@ func ParseTagging(data []byte, limit TagLimit) (map[string]string, error) {
tagSet := make(map[string]string, tLen)
for _, tag := range tagging.TagSet.Tags {
// validate tag key
// validate tag key length
if len(tag.Key) == 0 || len(tag.Key) > 128 {
debuglogger.Logf("tag key should 0 < tag.Key <= 128, key: %v", tag.Key)
return nil, s3err.GetAPIError(s3err.ErrInvalidTagKey)
}
// validate tag value
// validate tag key string chars
if !tagRule.MatchString(tag.Key) {
debuglogger.Logf("invalid tag key: %s", tag.Key)
return nil, s3err.GetAPIError(s3err.ErrInvalidTagKey)
}
// validate tag value length
if len(tag.Value) > 256 {
debuglogger.Logf("invalid long tag value: (length): %v, (value): %v", len(tag.Value), tag.Value)
return nil, s3err.GetAPIError(s3err.ErrInvalidTagValue)
}
// validate tag value string chars
if !tagRule.MatchString(tag.Value) {
debuglogger.Logf("invalid tag value: %s", tag.Value)
return nil, s3err.GetAPIError(s3err.ErrInvalidTagValue)
}
// make sure there are no duplicate keys
_, ok := tagSet[tag.Key]
if ok {