diff --git a/sensors/artifacts/git.go b/sensors/artifacts/git.go index 6e6d26ed84..0965082a21 100644 --- a/sensors/artifacts/git.go +++ b/sensors/artifacts/git.go @@ -20,6 +20,8 @@ import ( "fmt" "io/ioutil" "os" + "path" + "strings" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" @@ -44,6 +46,8 @@ var ( "refs/*:refs/*", "HEAD:refs/heads/HEAD", } + + notAllowedInPath = []string{"..", "~", "\\"} ) type GitArtifactReader struct { @@ -52,6 +56,15 @@ type GitArtifactReader struct { // NewGitReader returns a new git reader func NewGitReader(gitArtifact *v1alpha1.GitArtifact) (*GitArtifactReader, error) { + if gitArtifact == nil { + return nil, fmt.Errorf("nil git artifact") + } + for _, na := range notAllowedInPath { + if strings.Contains(gitArtifact.FilePath, na) { + return nil, fmt.Errorf("%q is not allowed in the filepath", na) + } + } + return &GitArtifactReader{ artifact: gitArtifact, }, nil @@ -176,8 +189,16 @@ func (g *GitArtifactReader) readFromRepository(r *git.Repository, dir string) ([ return nil, fmt.Errorf("failed to pull latest updates. err: %+v", err) } } - - return ioutil.ReadFile(fmt.Sprintf("%s/%s", dir, g.artifact.FilePath)) + filePath := fmt.Sprintf("%s/%s", dir, g.artifact.FilePath) + // symbol link is not allowed due to security concern + isSymbolLink, err := isSymbolLink(filePath) + if err != nil { + return nil, err + } + if isSymbolLink { + return nil, fmt.Errorf("%q is a symbol link which is not allowed", g.artifact.FilePath) + } + return ioutil.ReadFile(filePath) } func (g *GitArtifactReader) getBranchOrTag() *git.CheckoutOptions { @@ -241,3 +262,14 @@ func (g *GitArtifactReader) Read() ([]byte, error) { } return g.readFromRepository(r, cloneDir) } + +func isSymbolLink(filepath string) (bool, error) { + fi, err := os.Lstat(path.Clean(filepath)) + if err != nil { + return false, err + } + if fi.Mode()&os.ModeSymlink != 0 { + return true, nil + } + return false, nil +}