|
4 | 4 | "fmt" |
5 | 5 | "log" |
6 | 6 | "net/http" |
| 7 | + "regexp" |
7 | 8 | "strings" |
8 | 9 | "time" |
9 | 10 |
|
|
24 | 25 | GetProjectSettingsResource func() schema.GroupVersionResource |
25 | 26 | ) |
26 | 27 |
|
| 28 | +// validBranchNameRegex defines allowed characters in branch names |
| 29 | +// Allows: letters, numbers, hyphens, underscores, forward slashes, and dots |
| 30 | +// Prevents: shell metacharacters, backticks, quotes, semicolons, pipes, etc. |
| 31 | +var validBranchNameRegex = regexp.MustCompile(`^[a-zA-Z0-9/_.-]+$`) |
| 32 | + |
| 33 | +// validateBranchName checks if a branch name is safe to use in git operations |
| 34 | +// Returns error if the branch name contains potentially dangerous characters |
| 35 | +func validateBranchName(branchName string) error { |
| 36 | + if branchName == "" { |
| 37 | + return fmt.Errorf("branch name cannot be empty") |
| 38 | + } |
| 39 | + if !validBranchNameRegex.MatchString(branchName) { |
| 40 | + return fmt.Errorf("branch name contains invalid characters (allowed: a-z, A-Z, 0-9, /, _, -, .)") |
| 41 | + } |
| 42 | + // Prevent branch names that start with special characters |
| 43 | + if strings.HasPrefix(branchName, ".") || strings.HasPrefix(branchName, "-") { |
| 44 | + return fmt.Errorf("branch name cannot start with '.' or '-'") |
| 45 | + } |
| 46 | + // Prevent branch names with ".." (path traversal) or "//" (double slashes) |
| 47 | + if strings.Contains(branchName, "..") || strings.Contains(branchName, "//") { |
| 48 | + return fmt.Errorf("branch name cannot contain '..' or '//'") |
| 49 | + } |
| 50 | + return nil |
| 51 | +} |
| 52 | + |
27 | 53 | // CreateProjectBugFixWorkflow handles POST /api/projects/:projectName/bugfix-workflows |
28 | 54 | // Creates a new BugFix Workspace from either GitHub Issue URL or text description |
29 | 55 | func CreateProjectBugFixWorkflow(c *gin.Context) { |
@@ -165,6 +191,11 @@ func CreateProjectBugFixWorkflow(c *gin.Context) { |
165 | 191 | branch := "main" |
166 | 192 | if req.BranchName != nil && *req.BranchName != "" { |
167 | 193 | branch = *req.BranchName |
| 194 | + // Validate user-provided branch name for security |
| 195 | + if err := validateBranchName(branch); err != nil { |
| 196 | + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid branch name", "details": err.Error()}) |
| 197 | + return |
| 198 | + } |
168 | 199 | } else { |
169 | 200 | // Auto-generate branch name: bugfix/gh-{issue-number} |
170 | 201 | branch = fmt.Sprintf("bugfix/gh-%d", githubIssue.Number) |
|
0 commit comments