s3: apply destination retention on copies instead of inheriting it (#11773)

* s3: apply destination retention on copies instead of inheriting it

CopyObject carried the source object's retention mode, retain-until date
and legal hold into the destination entry, so a copy onto a bucket with
default COMPLIANCE retention produced an unlocked object that could be
deleted early. Copied objects now take their retention from the copy
request's lock headers or the destination bucket's default, matching
PUT semantics; a versioned self-copy gets the same treatment while an
unversioned metadata-only self-copy keeps the object's existing lock.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* s3: validate lock headers on metadata-only self-copies

---------

Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Chris LuandDevin authored and GitHub committed 2026-10-16 19:52:10 -07:00
1 parent 2d06e2d6c1
commit 44657988ea
2 files changed
+67

No files matched your search

+17
View File
@@ -79,3 +79,20 @@ func TestVeeamObjectLockBugFix(t *testing.T) {
assert.True(t, enabled, "Object Lock should be enabled when constant is used")
})
}
// Copied objects get their own retention from the request or the destination
// bucket's default; the source's lock keys never carry into the destination
// entry.
func TestCopyDoesNotInheritLockKeys(t *testing.T) {
// The destination-Extended copy loop filters on isCopyLockKey, so
// retention and legal hold never carry over from the source entry.
for _, key := range []string{
s3_constants.ExtObjectLockModeKey,
s3_constants.ExtRetentionUntilDateKey,
s3_constants.ExtLegalHoldKey,
} {
assert.True(t, isCopyLockKey(key), "%s must be filtered from a copy destination", key)
}
assert.False(t, isCopyLockKey(s3_constants.ExtAmzOwnerKey))
assert.False(t, isCopyLockKey("custom-key"))
}