@@ -197,8 +197,13 @@ func (j *GitCommitJob) cloneAndReplace(ctx context.Context) {
197197 paths = []string {"/" }
198198 }
199199
200- for _ , path := range paths {
201- updatePath := filepath .Join (tmp , path )
200+ for _ , p := range paths {
201+ updatePath := filepath .Clean (filepath .Join (tmp , p ))
202+ if pathEscapesBase (tmp , p ) {
203+ err = j .updateErrorStatus (ctx , gitrepo , fmt .Errorf ("path %q resolves outside the repository root" , p ))
204+ logger .V (1 ).Info ("Skipping path outside repository root" , "path" , p , "error" , err )
205+ return
206+ }
202207 if err := update .WithSetters (updatePath , updatePath , scans ); err != nil {
203208 err = j .updateErrorStatus (ctx , gitrepo , err )
204209 logger .V (1 ).Info ("Cannot update image tags in repo" , "error" , err )
@@ -259,6 +264,13 @@ func (j *GitCommitJob) updateErrorStatus(ctx context.Context, gitrepo *fleet.Git
259264 return errutil .NewAggregate (merr )
260265}
261266
267+ // pathEscapesBase reports whether relPath, when resolved relative to base, points outside base.
268+ func pathEscapesBase (base , relPath string ) bool {
269+ resolved := filepath .Clean (filepath .Join (base , relPath ))
270+ clean := filepath .Clean (base )
271+ return ! strings .HasPrefix (resolved , clean + string (os .PathSeparator )) && resolved != clean
272+ }
273+
262274func shouldSync (gitrepo * fleet.GitRepo ) bool {
263275 interval := gitrepo .Spec .ImageSyncInterval
264276 if interval == nil || interval .Seconds () == 0.0 {
0 commit comments