From af3ae491975b4f631f929d44d7320b605684c029 Mon Sep 17 00:00:00 2001 From: Sungkyu Yoo Date: Sun, 19 Apr 2026 22:32:23 +0900 Subject: [PATCH 1/2] Potential fix for code scanning alert no. 12: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- internal/services/s3/provider.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/services/s3/provider.go b/internal/services/s3/provider.go index ba44a90..8b070ea 100644 --- a/internal/services/s3/provider.go +++ b/internal/services/s3/provider.go @@ -27,6 +27,8 @@ import ( const defaultAccountID = plugin.DefaultAccountID +var uploadIDPattern = regexp.MustCompile(`^[a-fA-F0-9]{16,128}$`) + // S3Provider implements plugin.ServicePlugin using FileStore and MetadataStore. type S3Provider struct { fileStore *FileStore @@ -854,6 +856,9 @@ func (p *S3Provider) uploadPart(_ context.Context, bucket, key, uploadID, partNu if err != nil || partNumber < 1 { return xmlError("InvalidArgument", "invalid part number", http.StatusBadRequest), nil } + if !uploadIDPattern.MatchString(uploadID) { + return xmlError("InvalidArgument", "invalid upload id", http.StatusBadRequest), nil + } if _, err := p.metaStore.GetMultipartUpload(uploadID); err != nil { if errors.Is(err, ErrUploadNotFound) { From 85e710eced5cfb49597e20ec4569fa96c3c25d5f Mon Sep 17 00:00:00 2001 From: Sung-Kyu Yoo Date: Mon, 20 Apr 2026 19:36:22 +0900 Subject: [PATCH 2/2] fix: centralize upload ID validation across all multipart handlers Replace loose uploadIDPattern regex with shared.ValidateUploadID (exact 32-char lowercase hex matching generateUploadID output), add missing validation to listParts, and align error message casing to "uploadId". --- internal/services/s3/provider.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/services/s3/provider.go b/internal/services/s3/provider.go index 0039879..a7d17eb 100644 --- a/internal/services/s3/provider.go +++ b/internal/services/s3/provider.go @@ -28,8 +28,6 @@ import ( const defaultAccountID = plugin.DefaultAccountID -var uploadIDPattern = regexp.MustCompile(`^[a-fA-F0-9]{16,128}$`) - // S3Provider implements plugin.ServicePlugin using FileStore and MetadataStore. type S3Provider struct { fileStore *FileStore @@ -851,8 +849,8 @@ func (p *S3Provider) uploadPart(_ context.Context, bucket, key, uploadID, partNu if err != nil || partNumber < 1 { return xmlError("InvalidArgument", "invalid part number", http.StatusBadRequest), nil } - if !uploadIDPattern.MatchString(uploadID) { - return xmlError("InvalidArgument", "invalid upload id", http.StatusBadRequest), nil + if !shared.ValidateUploadID(uploadID) { + return xmlError("InvalidArgument", "invalid uploadId", http.StatusBadRequest), nil } if _, err := p.metaStore.GetMultipartUpload(uploadID); err != nil { @@ -1010,6 +1008,9 @@ func (p *S3Provider) listMultipartUploads(_ context.Context, bucket string) (*pl } func (p *S3Provider) listParts(_ context.Context, bucket, key, uploadID string) (*plugin.Response, error) { + if !shared.ValidateUploadID(uploadID) { + return xmlError("InvalidArgument", "invalid uploadId", http.StatusBadRequest), nil + } if _, err := p.metaStore.GetMultipartUpload(uploadID); err != nil { if errors.Is(err, ErrUploadNotFound) { return xmlError("NoSuchUpload", "upload not found", http.StatusNotFound), nil