diff --git a/internal/services/ecr/store.go b/internal/services/ecr/store.go index bffca9e..999e599 100644 --- a/internal/services/ecr/store.go +++ b/internal/services/ecr/store.go @@ -12,6 +12,7 @@ import ( "fmt" "os" "path/filepath" + "strings" "time" "github.com/skyoo2003/devcloud/internal/storage/sqlite" @@ -387,6 +388,15 @@ func (s *ECRStore) InitiateLayerUpload(accountID, repoName string) (string, erro // UploadLayerPart saves layer part blob to the filesystem and records the part metadata. func (s *ECRStore) UploadLayerPart(accountID, repoName, uploadID string, partFirst, partLast int64, blob []byte) error { + // uploadID is used as a filesystem path component; enforce generated-ID format. + // InitiateLayerUpload creates 16 random bytes encoded as 32 lowercase hex chars. + if len(uploadID) != 32 || uploadID != strings.ToLower(uploadID) { + return ErrLayerUploadNotFound + } + if _, err := hex.DecodeString(uploadID); err != nil { + return ErrLayerUploadNotFound + } + // Verify upload exists. var exists int _ = s.db().QueryRow(`SELECT COUNT(*) FROM layers WHERE upload_id=? AND repo_name=? AND account_id=?`, uploadID, repoName, accountID).Scan(&exists)