feat(backend): validate repo name

Ayman Bagabas created

only allow alphanumeric, dashes, underscores, periods, and slashes

Change summary

server/backend/sqlite/sqlite.go | 15 +++++++++++++++
server/utils/utils.go           | 15 +++++++++++++++
2 files changed, 30 insertions(+)

Detailed changes

server/backend/sqlite/sqlite.go 🔗

@@ -123,6 +123,10 @@ func (d *SqliteBackend) SetAnonAccess(level backend.AccessLevel) error {
 // It implements backend.Backend.
 func (d *SqliteBackend) CreateRepository(name string, opts backend.RepositoryOptions) (backend.Repository, error) {
 	name = utils.SanitizeRepo(name)
+	if err := utils.ValidateRepo(name); err != nil {
+		return nil, err
+	}
+
 	repo := name + ".git"
 	rp := filepath.Join(d.reposPath(), repo)
 
@@ -165,6 +169,10 @@ func (d *SqliteBackend) CreateRepository(name string, opts backend.RepositoryOpt
 // ImportRepository imports a repository from remote.
 func (d *SqliteBackend) ImportRepository(name string, remote string, opts backend.RepositoryOptions) (backend.Repository, error) {
 	name = utils.SanitizeRepo(name)
+	if err := utils.ValidateRepo(name); err != nil {
+		return nil, err
+	}
+
 	repo := name + ".git"
 	rp := filepath.Join(d.reposPath(), repo)
 
@@ -217,7 +225,14 @@ func (d *SqliteBackend) DeleteRepository(name string) error {
 // It implements backend.Backend.
 func (d *SqliteBackend) RenameRepository(oldName string, newName string) error {
 	oldName = utils.SanitizeRepo(oldName)
+	if err := utils.ValidateRepo(oldName); err != nil {
+		return err
+	}
+
 	newName = utils.SanitizeRepo(newName)
+	if err := utils.ValidateRepo(newName); err != nil {
+		return err
+	}
 	oldRepo := oldName + ".git"
 	newRepo := newName + ".git"
 	op := filepath.Join(d.reposPath(), oldRepo)

server/utils/utils.go 🔗

@@ -33,3 +33,18 @@ func ValidateUsername(username string) error {
 
 	return nil
 }
+
+// ValidateRepo returns an error if the given repository name is invalid.
+func ValidateRepo(repo string) error {
+	if repo == "" {
+		return fmt.Errorf("repo cannot be empty")
+	}
+
+	for _, r := range repo {
+		if !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != '-' && r != '_' && r != '.' && r != '/' {
+			return fmt.Errorf("repo can only contain letters, numbers, hyphens, underscores, periods, and slashes")
+		}
+	}
+
+	return nil
+}