@@ -29,6 +29,7 @@ import (
2929 "strings"
3030 "time"
3131
32+ securejoin "github.com/cyphar/filepath-securejoin"
3233 "github.com/go-git/go-git/v5/plumbing/format/gitignore"
3334 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3435
@@ -83,8 +84,7 @@ func (s Storage) SetArtifactURL(artifact *sourcev1.Artifact) {
8384 artifact .URL = fmt .Sprintf ("http://%s/%s" , s .Hostname , artifact .Path )
8485}
8586
86- // SetHostname sets the hostname of the given URL string to the current Storage.Hostname
87- // and returns the result.
87+ // SetHostname sets the hostname of the given URL string to the current Storage.Hostname and returns the result.
8888func (s Storage ) SetHostname (URL string ) string {
8989 u , err := url .Parse (URL )
9090 if err != nil {
@@ -106,8 +106,7 @@ func (s *Storage) RemoveAll(artifact sourcev1.Artifact) error {
106106 return os .RemoveAll (dir )
107107}
108108
109- // RemoveAllButCurrent removes all files for the given v1beta1.Artifact base dir,
110- // excluding the current one.
109+ // RemoveAllButCurrent removes all files for the given v1beta1.Artifact base dir, excluding the current one.
111110func (s * Storage ) RemoveAllButCurrent (artifact sourcev1.Artifact ) error {
112111 localPath := s .LocalPath (artifact )
113112 dir := filepath .Dir (localPath )
@@ -132,8 +131,7 @@ func (s *Storage) RemoveAllButCurrent(artifact sourcev1.Artifact) error {
132131 return nil
133132}
134133
135- // ArtifactExist returns a boolean indicating whether the v1beta1.Artifact exists in storage
136- // and is a regular file.
134+ // ArtifactExist returns a boolean indicating whether the v1beta1.Artifact exists in storage and is a regular file.
137135func (s * Storage ) ArtifactExist (artifact sourcev1.Artifact ) bool {
138136 fi , err := os .Lstat (s .LocalPath (artifact ))
139137 if err != nil {
@@ -142,14 +140,13 @@ func (s *Storage) ArtifactExist(artifact sourcev1.Artifact) bool {
142140 return fi .Mode ().IsRegular ()
143141}
144142
145- // ArchiveFileFilter must return true if a file should not be included
146- // in the archive after inspecting the given path and/or os.FileInfo.
143+ // ArchiveFileFilter must return true if a file should not be included in the archive after inspecting the given path
144+ // and/or os.FileInfo.
147145type ArchiveFileFilter func (p string , fi os.FileInfo ) bool
148146
149- // SourceIgnoreFilter returns an ArchiveFileFilter that filters out
150- // files matching sourceignore.VCSPatterns and any of the provided
151- // patterns. If an empty gitignore.Pattern slice is given, the matcher
152- // is set to sourceignore.NewDefaultMatcher.
147+ // SourceIgnoreFilter returns an ArchiveFileFilter that filters out files matching sourceignore.VCSPatterns and any of
148+ // the provided patterns.
149+ // If an empty gitignore.Pattern slice is given, the matcher is set to sourceignore.NewDefaultMatcher.
153150func SourceIgnoreFilter (ps []gitignore.Pattern , domain []string ) ArchiveFileFilter {
154151 matcher := sourceignore .NewDefaultMatcher (ps , domain )
155152 if len (ps ) > 0 {
@@ -163,10 +160,9 @@ func SourceIgnoreFilter(ps []gitignore.Pattern, domain []string) ArchiveFileFilt
163160 }
164161}
165162
166- // Archive atomically archives the given directory as a tarball to the
167- // given v1beta1.Artifact path, excluding directories and any
168- // ArchiveFileFilter matches. If successful, it sets the checksum and
169- // last update time on the artifact.
163+ // Archive atomically archives the given directory as a tarball to the given v1beta1.Artifact path, excluding
164+ // directories and any ArchiveFileFilter matches.
165+ // If successful, it sets the checksum and last update time on the artifact.
170166func (s * Storage ) Archive (artifact * sourcev1.Artifact , dir string , filter ArchiveFileFilter ) (err error ) {
171167 if f , err := os .Stat (dir ); os .IsNotExist (err ) || ! f .IsDir () {
172168 return fmt .Errorf ("invalid dir path: %s" , dir )
@@ -341,9 +337,8 @@ func (s *Storage) Copy(artifact *sourcev1.Artifact, reader io.Reader) (err error
341337 return nil
342338}
343339
344- // CopyFromPath atomically copies the contents of the given path to the path of
345- // the v1beta1.Artifact. If successful, the checksum and last update time on the
346- // artifact is set.
340+ // CopyFromPath atomically copies the contents of the given path to the path of the v1beta1.Artifact.
341+ // If successful, the checksum and last update time on the artifact is set.
347342func (s * Storage ) CopyFromPath (artifact * sourcev1.Artifact , path string ) (err error ) {
348343 f , err := os .Open (path )
349344 if err != nil {
@@ -353,10 +348,10 @@ func (s *Storage) CopyFromPath(artifact *sourcev1.Artifact, path string) (err er
353348 return s .Copy (artifact , f )
354349}
355350
356- // CopyToPath copies the contents of the given artifact to the path.
351+ // CopyToPath copies the contents in the (sub)path of the given artifact to the given path.
357352func (s * Storage ) CopyToPath (artifact * sourcev1.Artifact , subPath , toPath string ) error {
358353 // create a tmp directory to store artifact
359- tmp , err := os .MkdirTemp ("" , "flux-include" )
354+ tmp , err := os .MkdirTemp ("" , "flux-include- " )
360355 if err != nil {
361356 return err
362357 }
@@ -371,7 +366,7 @@ func (s *Storage) CopyToPath(artifact *sourcev1.Artifact, subPath, toPath string
371366 defer f .Close ()
372367
373368 // untar the artifact
374- untarPath := filepath .Join (tmp , "tar " )
369+ untarPath := filepath .Join (tmp , "unpack " )
375370 if _ , err = untar .Untar (f , untarPath ); err != nil {
376371 return err
377372 }
@@ -382,15 +377,17 @@ func (s *Storage) CopyToPath(artifact *sourcev1.Artifact, subPath, toPath string
382377 }
383378
384379 // copy the artifact content to the destination dir
385- fromPath := filepath .Join (untarPath , subPath )
380+ fromPath , err := securejoin .SecureJoin (untarPath , subPath )
381+ if err != nil {
382+ return err
383+ }
386384 if err := fs .RenameWithFallback (fromPath , toPath ); err != nil {
387385 return err
388386 }
389387 return nil
390388}
391389
392- // Symlink creates or updates a symbolic link for the given v1beta1.Artifact
393- // and returns the URL for the symlink.
390+ // Symlink creates or updates a symbolic link for the given v1beta1.Artifact and returns the URL for the symlink.
394391func (s * Storage ) Symlink (artifact sourcev1.Artifact , linkName string ) (string , error ) {
395392 localPath := s .LocalPath (artifact )
396393 dir := filepath .Dir (localPath )
@@ -427,13 +424,16 @@ func (s *Storage) Lock(artifact sourcev1.Artifact) (unlock func(), err error) {
427424 return mutex .Lock ()
428425}
429426
430- // LocalPath returns the local path of the given artifact (that is: relative to
431- // the Storage.BasePath).
427+ // LocalPath returns the secure local path of the given artifact (that is: relative to the Storage.BasePath).
432428func (s * Storage ) LocalPath (artifact sourcev1.Artifact ) string {
433429 if artifact .Path == "" {
434430 return ""
435431 }
436- return filepath .Join (s .BasePath , artifact .Path )
432+ path , err := securejoin .SecureJoin (s .BasePath , artifact .Path )
433+ if err != nil {
434+ return ""
435+ }
436+ return path
437437}
438438
439439// newHash returns a new SHA1 hash.
0 commit comments