@@ -401,20 +401,33 @@ func saveArtifact(ctx context.Context, srcPath string) error {
401401 logger .WithField ("srcPath" , srcPath ).Info (ctx , "no need to save artifact - on overlapping volume" )
402402 return nil
403403 }
404+ // Normalize absolute paths (e.g. /tmp/artifact → tmp/artifact) so that
405+ // filepath.IsLocal can validate the result, and os.Root.Create can safely
406+ // write it within the outputs directory.
407+ relSrc := strings .TrimPrefix (strings .TrimSuffix (srcPath , "/" ), "/" )
408+ dstRel := relSrc + ".tgz"
409+ if ! filepath .IsLocal (dstRel ) {
410+ return fmt .Errorf ("path traversal in output artifact path %q" , srcPath )
411+ }
412+ artifactsDir := filepath .Join (varRunArgo , "outputs/artifacts" )
413+ dstPath := filepath .Join (artifactsDir , dstRel )
404414 if _ , err := os .Stat (srcPath ); os .IsNotExist (err ) { // might be optional, so we ignore
405415 logger .WithField ("srcPath" , srcPath ).WithError (err ).Warn (ctx , "cannot save artifact" )
406416 return nil
407417 }
408- dstPath := filepath .Join (varRunArgo , "/outputs/artifacts/" , strings .TrimSuffix (srcPath , "/" )+ ".tgz" )
409418 logger .WithFields (logging.Fields {
410419 "src" : srcPath ,
411420 "dst" : dstPath ,
412421 }).Info (ctx , "saving artifact" )
413- z := filepath .Dir (dstPath )
414- if err := os .MkdirAll (z , 0o755 ); err != nil { // chmod rwxr-xr-x
415- return fmt .Errorf ("failed to create directory %s: %w" , z , err )
422+ if err := os .MkdirAll (filepath .Dir (dstPath ), 0o755 ); err != nil { // chmod rwxr-xr-x
423+ return fmt .Errorf ("failed to create directory %s: %w" , filepath .Dir (dstPath ), err )
424+ }
425+ root , err := os .OpenRoot (artifactsDir )
426+ if err != nil {
427+ return fmt .Errorf ("failed to open artifacts output root: %w" , err )
416428 }
417- dst , err := os .Create (dstPath )
429+ defer root .Close ()
430+ dst , err := root .Create (dstRel )
418431 if err != nil {
419432 return fmt .Errorf ("failed to create destination %s: %w" , dstPath , err )
420433 }
@@ -435,6 +448,15 @@ func saveParameter(ctx context.Context, srcPath string) error {
435448 logger .WithField ("src" , srcPath ).Info (ctx , "no need to save parameter - on overlapping volume" )
436449 return nil
437450 }
451+ // Normalize absolute paths (e.g. /tmp/parameter → tmp/parameter) so that
452+ // filepath.IsLocal can validate the result, and os.Root.Create can safely
453+ // write it within the outputs directory.
454+ relPath := strings .TrimPrefix (srcPath , "/" )
455+ if ! filepath .IsLocal (relPath ) {
456+ return fmt .Errorf ("path traversal in output parameter path %q" , srcPath )
457+ }
458+ parametersDir := filepath .Join (varRunArgo , "outputs/parameters" )
459+ dstPath := filepath .Join (parametersDir , relPath )
438460 src , err := os .Open (filepath .Clean (srcPath ))
439461 if os .IsNotExist (err ) { // might be optional, so we ignore
440462 logger .WithField ("src" , srcPath ).WithError (err ).Error (ctx , "cannot save parameter, does not exist" )
@@ -444,16 +466,19 @@ func saveParameter(ctx context.Context, srcPath string) error {
444466 return fmt .Errorf ("failed to open %s: %w" , srcPath , err )
445467 }
446468 defer func () { _ = src .Close () }()
447- dstPath := varRunArgo + "/outputs/parameters/" + srcPath
448469 logger .WithFields (logging.Fields {
449470 "src" : srcPath ,
450471 "dst" : dstPath ,
451472 }).Info (ctx , "saving parameter" )
452- z := filepath .Dir (dstPath )
453- if mkdirErr := os .MkdirAll (z , 0o755 ); mkdirErr != nil { // chmod rwxr-xr-x
454- return fmt .Errorf ("failed to create directory %s: %w" , z , mkdirErr )
473+ if mkdirErr := os .MkdirAll (filepath .Dir (dstPath ), 0o755 ); mkdirErr != nil { // chmod rwxr-xr-x
474+ return fmt .Errorf ("failed to create directory %s: %w" , filepath .Dir (dstPath ), mkdirErr )
475+ }
476+ root , err := os .OpenRoot (parametersDir )
477+ if err != nil {
478+ return fmt .Errorf ("failed to open parameters output root: %w" , err )
455479 }
456- dst , err := os .Create (dstPath )
480+ defer root .Close ()
481+ dst , err := root .Create (relPath )
457482 if err != nil {
458483 return fmt .Errorf ("failed to create %s: %w" , srcPath , err )
459484 }
0 commit comments