in command-runner/internal/containers/docker/docker_run.go [448:495]
func (cr *dockerContainer) copyOut(hostPath string, containerPath string) common.Executor {
return func(ctx context.Context) error {
log.Ctx(ctx).Printf("Extracting content from '%s' to '%s'", containerPath, hostPath)
if out, _, err := cr.cli.CopyFromContainer(ctx, cr.id, containerPath); err != nil {
return fmt.Errorf("failed to copy content from container: %w", err)
} else {
tr := tar.NewReader(out)
defer out.Close()
for {
hdr, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return fmt.Errorf("error processing archive: %w", err)
}
hostPath := filepath.Join(hostPath, hdr.Name) // #nosec G305 - mitigated by following check
if !strings.HasPrefix(hostPath, filepath.Clean(hostPath)) {
return fmt.Errorf("content path is tainted: %s", hostPath)
}
switch hdr.Typeflag {
case tar.TypeDir:
if err := os.MkdirAll(hostPath, 0755); err != nil {
return err
}
case tar.TypeReg:
if err := os.MkdirAll(filepath.Dir(hostPath), 0755); err != nil {
return err
}
if f, err := os.Create(hostPath); err != nil {
return err
} else {
for {
_, err := io.CopyN(f, tr, 1024)
if err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("unable to copy tr file to output: %w", err)
}
}
}
}
}
}
return nil
}
}