summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2022-09-04 11:47:56 +0100
committerGitHub <noreply@github.com>2022-09-04 13:47:56 +0300
commite6b3be460840f1f982d5358198466e7d6f509d21 (patch)
treed3e4cb52c6a7df321e9b4ffdfe6f99f79d392b63 /modules
parent93a610a819688b54d4565b8cbbae7cc04c552073 (diff)
downloadgitea-e6b3be460840f1f982d5358198466e7d6f509d21.tar.gz
gitea-e6b3be460840f1f982d5358198466e7d6f509d21.zip
Add more checks in migration code (#21011)
When migrating add several more important sanity checks: * SHAs must be SHAs * Refs must be valid Refs * URLs must be reasonable Signed-off-by: Andrew Thornton <art27@cantab.net> Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <matti@mdranta.net>
Diffstat (limited to 'modules')
-rw-r--r--modules/git/ref.go28
-rw-r--r--modules/git/repo_commit_nogogit.go2
-rw-r--r--modules/git/sha1.go7
-rw-r--r--modules/migration/pullrequest.go9
-rw-r--r--modules/migration/release.go9
-rw-r--r--modules/migration/repo.go2
-rw-r--r--modules/validation/binding.go34
7 files changed, 48 insertions, 43 deletions
diff --git a/modules/git/ref.go b/modules/git/ref.go
index 9fd071ce58..2f459148a2 100644
--- a/modules/git/ref.go
+++ b/modules/git/ref.go
@@ -4,7 +4,10 @@
package git
-import "strings"
+import (
+ "regexp"
+ "strings"
+)
const (
// RemotePrefix is the base directory of the remotes information of git.
@@ -15,6 +18,29 @@ const (
pullLen = len(PullPrefix)
)
+// refNamePatternInvalid is regular expression with unallowed characters in git reference name
+// They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : anywhere.
+// They cannot have question-mark ?, asterisk *, or open bracket [ anywhere
+var refNamePatternInvalid = regexp.MustCompile(
+ `[\000-\037\177 \\~^:?*[]|` + // No absolutely invalid characters
+ `(?:^[/.])|` + // Not HasPrefix("/") or "."
+ `(?:/\.)|` + // no "/."
+ `(?:\.lock$)|(?:\.lock/)|` + // No ".lock/"" or ".lock" at the end
+ `(?:\.\.)|` + // no ".." anywhere
+ `(?://)|` + // no "//" anywhere
+ `(?:@{)|` + // no "@{"
+ `(?:[/.]$)|` + // no terminal '/' or '.'
+ `(?:^@$)`) // Not "@"
+
+// IsValidRefPattern ensures that the provided string could be a valid reference
+func IsValidRefPattern(name string) bool {
+ return !refNamePatternInvalid.MatchString(name)
+}
+
+func SanitizeRefPattern(name string) string {
+ return refNamePatternInvalid.ReplaceAllString(name, "_")
+}
+
// Reference represents a Git ref.
type Reference struct {
Name string
diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go
index e528af0ffb..efea307b37 100644
--- a/modules/git/repo_commit_nogogit.go
+++ b/modules/git/repo_commit_nogogit.go
@@ -138,7 +138,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id SHA1) (*Co
// ConvertToSHA1 returns a Hash object from a potential ID string
func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) {
- if len(commitID) == 40 && SHAPattern.MatchString(commitID) {
+ if len(commitID) == 40 && IsValidSHAPattern(commitID) {
sha1, err := NewIDFromString(commitID)
if err == nil {
return sha1, nil
diff --git a/modules/git/sha1.go b/modules/git/sha1.go
index 2da74733df..15f282c6e4 100644
--- a/modules/git/sha1.go
+++ b/modules/git/sha1.go
@@ -19,7 +19,12 @@ const EmptySHA = "0000000000000000000000000000000000000000"
const EmptyTreeSHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
// SHAPattern can be used to determine if a string is an valid sha
-var SHAPattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
+var shaPattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
+
+// IsValidSHAPattern will check if the provided string matches the SHA Pattern
+func IsValidSHAPattern(sha string) bool {
+ return shaPattern.MatchString(sha)
+}
// MustID always creates a new SHA1 from a [20]byte array with no validation of input.
func MustID(b []byte) SHA1 {
diff --git a/modules/migration/pullrequest.go b/modules/migration/pullrequest.go
index eaa0dd45e2..dd520cd63f 100644
--- a/modules/migration/pullrequest.go
+++ b/modules/migration/pullrequest.go
@@ -26,7 +26,7 @@ type PullRequest struct {
Updated time.Time
Closed *time.Time
Labels []*Label
- PatchURL string `yaml:"patch_url"`
+ PatchURL string `yaml:"patch_url"` // SECURITY: This must be safe to download directly from
Merged bool
MergedTime *time.Time `yaml:"merged_time"`
MergeCommitSHA string `yaml:"merge_commit_sha"`
@@ -37,6 +37,7 @@ type PullRequest struct {
Reactions []*Reaction
ForeignIndex int64
Context DownloaderContext `yaml:"-"`
+ EnsuredSafe bool `yaml:"ensured_safe"`
}
func (p *PullRequest) GetLocalIndex() int64 { return p.Number }
@@ -55,9 +56,9 @@ func (p PullRequest) GetGitRefName() string {
// PullRequestBranch represents a pull request branch
type PullRequestBranch struct {
- CloneURL string `yaml:"clone_url"`
- Ref string
- SHA string
+ CloneURL string `yaml:"clone_url"` // SECURITY: This must be safe to download from
+ Ref string // SECURITY: this must be a git.IsValidRefPattern
+ SHA string // SECURITY: this must be a git.IsValidSHAPattern
RepoName string `yaml:"repo_name"`
OwnerName string `yaml:"owner_name"`
}
diff --git a/modules/migration/release.go b/modules/migration/release.go
index cbdf01a3ed..923b3817b0 100644
--- a/modules/migration/release.go
+++ b/modules/migration/release.go
@@ -18,15 +18,16 @@ type ReleaseAsset struct {
DownloadCount *int `yaml:"download_count"`
Created time.Time
Updated time.Time
- DownloadURL *string `yaml:"download_url"`
+
+ DownloadURL *string `yaml:"download_url"` // SECURITY: It is the responsibility of downloader to make sure this is safe
// if DownloadURL is nil, the function should be invoked
- DownloadFunc func() (io.ReadCloser, error) `yaml:"-"`
+ DownloadFunc func() (io.ReadCloser, error) `yaml:"-"` // SECURITY: It is the responsibility of downloader to make sure this is safe
}
// Release represents a release
type Release struct {
- TagName string `yaml:"tag_name"`
- TargetCommitish string `yaml:"target_commitish"`
+ TagName string `yaml:"tag_name"` // SECURITY: This must pass git.IsValidRefPattern
+ TargetCommitish string `yaml:"target_commitish"` // SECURITY: This must pass git.IsValidRefPattern
Name string
Body string
Draft bool
diff --git a/modules/migration/repo.go b/modules/migration/repo.go
index d0d62de8da..75622595d9 100644
--- a/modules/migration/repo.go
+++ b/modules/migration/repo.go
@@ -12,7 +12,7 @@ type Repository struct {
IsPrivate bool `yaml:"is_private"`
IsMirror bool `yaml:"is_mirror"`
Description string
- CloneURL string `yaml:"clone_url"`
+ CloneURL string `yaml:"clone_url"` // SECURITY: This must be checked to ensure that is safe to be used
OriginalURL string `yaml:"original_url"`
DefaultBranch string
}
diff --git a/modules/validation/binding.go b/modules/validation/binding.go
index 7baa36ccc5..f08f632426 100644
--- a/modules/validation/binding.go
+++ b/modules/validation/binding.go
@@ -9,6 +9,8 @@ import (
"regexp"
"strings"
+ "code.gitea.io/gitea/modules/git"
+
"gitea.com/go-chi/binding"
"github.com/gobwas/glob"
)
@@ -24,30 +26,6 @@ const (
ErrRegexPattern = "RegexPattern"
)
-// GitRefNamePatternInvalid is regular expression with unallowed characters in git reference name
-// They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : anywhere.
-// They cannot have question-mark ?, asterisk *, or open bracket [ anywhere
-var GitRefNamePatternInvalid = regexp.MustCompile(`[\000-\037\177 \\~^:?*[]+`)
-
-// CheckGitRefAdditionalRulesValid check name is valid on additional rules
-func CheckGitRefAdditionalRulesValid(name string) bool {
- // Additional rules as described at https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
- if strings.HasPrefix(name, "/") || strings.HasSuffix(name, "/") ||
- strings.HasSuffix(name, ".") || strings.Contains(name, "..") ||
- strings.Contains(name, "//") || strings.Contains(name, "@{") ||
- name == "@" {
- return false
- }
- parts := strings.Split(name, "/")
- for _, part := range parts {
- if strings.HasSuffix(part, ".lock") || strings.HasPrefix(part, ".") {
- return false
- }
- }
-
- return true
-}
-
// AddBindingRules adds additional binding rules
func AddBindingRules() {
addGitRefNameBindingRule()
@@ -67,16 +45,10 @@ func addGitRefNameBindingRule() {
IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) {
str := fmt.Sprintf("%v", val)
- if GitRefNamePatternInvalid.MatchString(str) {
+ if !git.IsValidRefPattern(str) {
errs.Add([]string{name}, ErrGitRefName, "GitRefName")
return false, errs
}
-
- if !CheckGitRefAdditionalRulesValid(str) {
- errs.Add([]string{name}, ErrGitRefName, "GitRefName")
- return false, errs
- }
-
return true, errs
},
})