From 7b423ed1efce61341c08acb9c66a767df2e61e52 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Fri, 8 Mar 2024 20:46:58 +0100 Subject: [PATCH] fix: Fix path related security issues --- internal/v3/api/module.go | 12 ++++++++++++ internal/v3/api/release.go | 11 +++++++++++ internal/v3/backend/filesystem.go | 9 +++++++++ internal/v3/utils/path.go | 13 +++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 internal/v3/utils/path.go diff --git a/internal/v3/api/module.go b/internal/v3/api/module.go index 7c7c60a..43ec9ec 100644 --- a/internal/v3/api/module.go +++ b/internal/v3/api/module.go @@ -11,6 +11,7 @@ import ( "github.com/dadav/gorge/internal/log" "github.com/dadav/gorge/internal/v3/backend" + "github.com/dadav/gorge/internal/v3/utils" gen "github.com/dadav/gorge/pkg/gen/v3/openapi" ) @@ -29,6 +30,17 @@ type DeleteModule500Response struct { // DeleteModule - Delete module func (s *ModuleOperationsApi) DeleteModule(ctx context.Context, moduleSlug string, reason string) (gen.ImplResponse, error) { + if !utils.CheckModuleSlug(moduleSlug) { + err := errors.New("invalid module slug") + return gen.Response( + 400, + DeleteModule500Response{ + Message: err.Error(), + Errors: []string{err.Error()}, + }, + ), nil + } + err := backend.ConfiguredBackend.DeleteModuleBySlug(moduleSlug) if err == nil { return gen.Response(204, nil), nil diff --git a/internal/v3/api/release.go b/internal/v3/api/release.go index 82b9a6f..040f8b8 100644 --- a/internal/v3/api/release.go +++ b/internal/v3/api/release.go @@ -14,6 +14,7 @@ import ( "github.com/dadav/gorge/internal/config" "github.com/dadav/gorge/internal/v3/backend" + "github.com/dadav/gorge/internal/v3/utils" gen "github.com/dadav/gorge/pkg/gen/v3/openapi" ) @@ -65,6 +66,16 @@ type DeleteRelease500Response struct { // DeleteRelease - Delete module release func (s *ReleaseOperationsApi) DeleteRelease(ctx context.Context, releaseSlug string, reason string) (gen.ImplResponse, error) { + if !utils.CheckReleaseSlug(releaseSlug) { + err := errors.New("invalid release slug") + return gen.Response( + 400, + DeleteRelease500Response{ + Message: err.Error(), + Errors: []string{err.Error()}, + }, + ), nil + } err := backend.ConfiguredBackend.DeleteReleaseBySlug(releaseSlug) if err == nil { return gen.Response(204, nil), nil diff --git a/internal/v3/backend/filesystem.go b/internal/v3/backend/filesystem.go index 166d180..0a90f33 100644 --- a/internal/v3/backend/filesystem.go +++ b/internal/v3/backend/filesystem.go @@ -19,6 +19,7 @@ import ( "github.com/dadav/gorge/internal/config" "github.com/dadav/gorge/internal/log" "github.com/dadav/gorge/internal/model" + "github.com/dadav/gorge/internal/v3/utils" gen "github.com/dadav/gorge/pkg/gen/v3/openapi" "golang.org/x/mod/semver" ) @@ -139,7 +140,12 @@ func (s *FilesystemBackend) AddRelease(releaseData []byte) (*gen.Release, error) if err != nil { return nil, err } + releaseSlug := fmt.Sprintf("%s-%s", metadata.Name, metadata.Version) + if !utils.CheckReleaseSlug(releaseSlug) { + return nil, errors.New("invalid release slug") + } + if _, ok := s.Releases[releaseSlug]; ok { return nil, errors.New("release already exist") } @@ -428,6 +434,9 @@ func ReadReleaseMetadataFromBytes(data []byte) (*model.ReleaseMetadata, string, return nil, readme.String(), err } + if !utils.CheckModuleSlug(releaseMetadata.Name) { + return nil, readme.String(), errors.New("invalid module name") + } case "README.md": _, err = io.Copy(readme, tarReader) if err != nil { diff --git a/internal/v3/utils/path.go b/internal/v3/utils/path.go new file mode 100644 index 0000000..36390ae --- /dev/null +++ b/internal/v3/utils/path.go @@ -0,0 +1,13 @@ +package utils + +import "regexp" + +func CheckModuleSlug(slug string) bool { + r, _ := regexp.Compile(`^[a-zA-Z0-9]+[-\/][a-z][a-z0-9_]*$`) + return r.MatchString(slug) +} + +func CheckReleaseSlug(slug string) bool { + r, _ := regexp.Compile(`^[a-zA-Z0-9]+[-\/][a-z][a-z0-9_]*[-\/][0-9]+\.[0-9]+\.[0-9]+(?:[\-+].+)?$`) + return r.MatchString(slug) +}