From e6ab9e7b09d6c3e814ca0f39c8b8218b3ad3bcee Mon Sep 17 00:00:00 2001 From: 7y-9 Date: Mon, 8 Jun 2026 11:53:45 +0800 Subject: [PATCH] fix(s3api): reject zero default retention years (#9860) Problem: Default object-lock retention accepted an explicitly provided Years value of zero, even though a default retention period must be positive when present. Root cause: validateDefaultRetention rejected zero Days but only rejected negative Years, leaving YearsSet with Years=0 as a successful validation path. Fix: Treat an explicitly provided zero Years value as ErrInvalidRetentionPeriod, matching the existing Days validation. Reproduction: go test ./weed/s3api -run TestValidateDefaultRetention -count=1 failed before the fix because the Zero years case returned nil. Validation: go test ./weed/s3api -run TestValidateDefaultRetention -count=1; go test ./weed/s3api -count=1; git diff --check; git diff --cached --check --- weed/s3api/object_lock_utils.go | 5 +++++ weed/s3api/s3api_object_retention_test.go | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/weed/s3api/object_lock_utils.go b/weed/s3api/object_lock_utils.go index d58bc7b8e..a3eddca45 100644 --- a/weed/s3api/object_lock_utils.go +++ b/weed/s3api/object_lock_utils.go @@ -326,6 +326,11 @@ func validateDefaultRetention(retention *DefaultRetention) error { return ErrInvalidRetentionPeriod } + // Check for invalid Years value (zero is invalid when explicitly provided) + if retention.YearsSet && retention.Years == 0 { + return ErrInvalidRetentionPeriod + } + // Check for neither Days nor Years being specified if !retention.DaysSet && !retention.YearsSet { return ErrDefaultRetentionMissingPeriod diff --git a/weed/s3api/s3api_object_retention_test.go b/weed/s3api/s3api_object_retention_test.go index 34c772acd..be42df700 100644 --- a/weed/s3api/s3api_object_retention_test.go +++ b/weed/s3api/s3api_object_retention_test.go @@ -786,6 +786,16 @@ func TestValidateDefaultRetention(t *testing.T) { expectError: true, errorMsg: "default retention must specify either Days or Years", }, + { + name: "Zero years", + retention: &DefaultRetention{ + Mode: "GOVERNANCE", + Years: 0, + YearsSet: true, + }, + expectError: true, + errorMsg: "invalid retention period specified", + }, } for _, tt := range tests {