diff --git a/backend/posix/posix.go b/backend/posix/posix.go
index 37eb7eac..f437de18 100644
--- a/backend/posix/posix.go
+++ b/backend/posix/posix.go
@@ -2038,8 +2038,9 @@ func (p *Posix) CopyObject(ctx context.Context, input *s3.CopyObjectInput) (*s3.
 			return &s3.CopyObjectOutput{}, s3err.GetAPIError(s3err.ErrInvalidCopyDest)
 		}
 
-		for key := range mdmap {
-			err := p.meta.DeleteAttribute(dstBucket, dstObject, key)
+		for k := range mdmap {
+			err := p.meta.DeleteAttribute(dstBucket, dstObject,
+				fmt.Sprintf("%v.%v", metaHdr, k))
 			if err != nil && !errors.Is(err, meta.ErrNoSuchKey) {
 				return nil, fmt.Errorf("delete user metadata: %w", err)
 			}
diff --git a/tests/integration/tests.go b/tests/integration/tests.go
index 80b7660c..7acca091 100644
--- a/tests/integration/tests.go
+++ b/tests/integration/tests.go
@@ -4567,6 +4567,11 @@ func CopyObject_copy_to_itself_invalid_directive(s *S3Conf) error {
 
 func CopyObject_to_itself_with_new_metadata(s *S3Conf) error {
 	testName := "CopyObject_to_itself_with_new_metadata"
+
+	meta := map[string]string{
+		"Hello": "World",
+	}
+
 	return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
 		obj := "my-obj"
 		err := putObjects(s3client, []string{obj}, bucket)
@@ -4575,12 +4580,41 @@ func CopyObject_to_itself_with_new_metadata(s *S3Conf) error {
 		}
 		ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
 		_, err = s3client.CopyObject(ctx, &s3.CopyObjectInput{
-			Bucket:     &bucket,
-			Key:        &obj,
-			CopySource: getPtr(fmt.Sprintf("%v/%v", bucket, obj)),
-			Metadata: map[string]string{
-				"Hello": "World",
-			},
+			Bucket:            &bucket,
+			Key:               &obj,
+			CopySource:        getPtr(fmt.Sprintf("%v/%v", bucket, obj)),
+			Metadata:          meta,
+			MetadataDirective: types.MetadataDirectiveReplace,
+		})
+		cancel()
+		if err != nil {
+			return err
+		}
+
+		ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
+		resp, err := s3client.HeadObject(ctx, &s3.HeadObjectInput{
+			Bucket: &bucket,
+			Key:    &obj,
+		})
+		cancel()
+		if err != nil {
+			return err
+		}
+
+		if !areMapsSame(resp.Metadata, meta) {
+			return fmt.Errorf("expected uploaded object metadata to be %v, instead got %v", meta, resp.Metadata)
+		}
+
+		// verify updating metadata has correct meta
+		meta = map[string]string{
+			"New": "Metadata",
+		}
+		ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
+		_, err = s3client.CopyObject(ctx, &s3.CopyObjectInput{
+			Bucket:            &bucket,
+			Key:               &obj,
+			CopySource:        getPtr(fmt.Sprintf("%v/%v", bucket, obj)),
+			Metadata:          meta,
 			MetadataDirective: types.MetadataDirectiveReplace,
 		})
 		cancel()
@@ -4588,6 +4622,20 @@ func CopyObject_to_itself_with_new_metadata(s *S3Conf) error {
 			return err
 		}
 
+		ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
+		resp, err = s3client.HeadObject(ctx, &s3.HeadObjectInput{
+			Bucket: &bucket,
+			Key:    &obj,
+		})
+		cancel()
+		if err != nil {
+			return err
+		}
+
+		if !areMapsSame(resp.Metadata, meta) {
+			return fmt.Errorf("expected uploaded object metadata to be %v, instead got %v", meta, resp.Metadata)
+		}
+
 		return nil
 	})
 }
diff --git a/tests/integration/utils.go b/tests/integration/utils.go
index c611d9b2..8c29f05f 100644
--- a/tests/integration/utils.go
+++ b/tests/integration/utils.go
@@ -428,12 +428,15 @@ func getPtr(str string) *string {
 	return &str
 }
 
+// mp1 needs to be the response from the server
+// mp2 needs to be the expected values
+// The keys from the server are always converted to lowercase
 func areMapsSame(mp1, mp2 map[string]string) bool {
 	if len(mp1) != len(mp2) {
 		return false
 	}
-	for key, val := range mp1 {
-		if mp2[key] != val {
+	for key, val := range mp2 {
+		if mp1[strings.ToLower(key)] != val {
 			return false
 		}
 	}