Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions api/cluster/EnvironmentRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/devtron-labs/devtron/pkg/cluster/environment/read"
"github.com/devtron-labs/devtron/util/commonEnforcementFunctionsUtil"
"net/http"
"regexp"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -106,6 +107,34 @@ func NewEnvironmentRestHandlerImpl(svc request.EnvironmentService, environmentRe
}
}

var (
// Regex patterns for environment name validation
envNameAlphanumericRegex = regexp.MustCompile(`^[a-z0-9-]+$`)
envNameNoStartEndHyphen = regexp.MustCompile(`^(?![-]).*[^-]$`)
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern ^(?![-]).*[^-]$ will fail for single-character names (e.g., 'a') because it requires at least two characters: one that doesn't match the negative lookahead and one that isn't a hyphen at the end. Consider using ^[^-].*[^-]$|^[^-]$ to handle single non-hyphen characters, or simplify to ^[^-]([a-z0-9-]*[^-])?$.

Suggested change
envNameNoStartEndHyphen = regexp.MustCompile(`^(?![-]).*[^-]$`)
envNameNoStartEndHyphen = regexp.MustCompile(`^[^-]([a-z0-9-]*[^-])?$`)

Copilot uses AI. Check for mistakes.
envNameLengthRegex = regexp.MustCompile(`^.{1,16}$`)
)

// validateEnvironmentName validates the environment name against multiple regex patterns
// Note: Required validation is already handled by struct validation tag
func (impl EnvironmentRestHandlerImpl) validateEnvironmentName(envName string) error {
// Validation 1: Use only lowercase alphanumeric characters or '-'
if !envNameAlphanumericRegex.MatchString(envName) {
return errors.New("Use only lowercase alphanumeric characters or '-'")
}

// Validation 2: Cannot start/end with '-'
if !envNameNoStartEndHyphen.MatchString(envName) {
return errors.New("Cannot start/end with '-'")
}

// Validation 3: Minimum 1 and Maximum 16 characters required
if !envNameLengthRegex.MatchString(envName) {
return errors.New("Minimum 1 and Maximum 16 characters required")
Comment on lines +130 to +131
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The length validation using regex ^.{1,16}$ is less efficient and less clear than using len(envName). Consider replacing this with a simple length check: if len(envName) < 1 || len(envName) > 16. This is more performant and easier to understand.

Copilot uses AI. Check for mistakes.
}

Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All three validations could be combined into a single comprehensive regex pattern ^[a-z0-9]([a-z0-9-]{0,14}[a-z0-9])?$, which would be more efficient (single pass) and simpler to maintain. This pattern enforces: starts with alphanumeric, ends with alphanumeric, allows hyphens in the middle, and limits length to 1-16 characters.

Suggested change
// Regex patterns for environment name validation
envNameAlphanumericRegex = regexp.MustCompile(`^[a-z0-9-]+$`)
envNameNoStartEndHyphen = regexp.MustCompile(`^(?![-]).*[^-]$`)
envNameLengthRegex = regexp.MustCompile(`^.{1,16}$`)
)
// validateEnvironmentName validates the environment name against multiple regex patterns
// Note: Required validation is already handled by struct validation tag
func (impl EnvironmentRestHandlerImpl) validateEnvironmentName(envName string) error {
// Validation 1: Use only lowercase alphanumeric characters or '-'
if !envNameAlphanumericRegex.MatchString(envName) {
return errors.New("Use only lowercase alphanumeric characters or '-'")
}
// Validation 2: Cannot start/end with '-'
if !envNameNoStartEndHyphen.MatchString(envName) {
return errors.New("Cannot start/end with '-'")
}
// Validation 3: Minimum 1 and Maximum 16 characters required
if !envNameLengthRegex.MatchString(envName) {
return errors.New("Minimum 1 and Maximum 16 characters required")
}
// Comprehensive regex pattern for environment name validation:
// - Only lowercase alphanumeric and hyphens
// - Must start and end with alphanumeric
// - Hyphens allowed only in the middle
// - Length: 1-16 characters
envNameComprehensiveRegex = regexp.MustCompile(`^[a-z0-9]([a-z0-9-]{0,14}[a-z0-9])?$`)
)
// validateEnvironmentName validates the environment name against multiple regex patterns
// Note: Required validation is already handled by struct validation tag
func (impl EnvironmentRestHandlerImpl) validateEnvironmentName(envName string) error {
// Validate using a single comprehensive regex
if !envNameComprehensiveRegex.MatchString(envName) {
return errors.New("Environment name must be 1-16 characters, use only lowercase alphanumeric characters or '-', cannot start or end with '-'")
}

Copilot uses AI. Check for mistakes.
return nil
}

func (impl EnvironmentRestHandlerImpl) Create(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
userId, err := impl.userService.GetLoggedInUser(r)
Expand All @@ -128,6 +157,13 @@ func (impl EnvironmentRestHandlerImpl) Create(w http.ResponseWriter, r *http.Req
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
// Validate environment name
err = impl.validateEnvironmentName(bean.Environment)
if err != nil {
impl.logger.Errorw("environment name validation err, Create", "err", err, "envName", bean.Environment)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}

// RBAC enforcer applying
token := r.Header.Get("token")
Expand Down
Loading