build: gate local delete outputs

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2026-06-10 16:41:10 +02:00
parent 473c6ef306
commit b6e1b7328f
14 changed files with 380 additions and 148 deletions
+63
View File
@@ -1329,6 +1329,69 @@ func CreateExports(entries []*buildflags.ExportEntry) ([]client.ExportEntry, []s
return outs, localPaths, nil
}
func ValidateLocalExportDelete(outputs []client.ExportEntry, allowDelete bool) error {
for _, ex := range outputs {
if ex.Type != client.ExporterLocal {
continue
}
mode, err := client.ParseLocalExporterMode(ex.Attrs["mode"])
if err != nil {
return err
}
if mode != client.LocalExporterModeDelete || allowDelete {
continue
}
ok, err := isSafeLocalDeleteDest(ex.OutputDir)
if err != nil {
return err
}
if !ok {
return errors.Errorf("local output mode=delete for destination %q requires --allow=%s", ex.OutputDir, buildflags.EntitlementBuildxLocalDelete)
}
}
return nil
}
func isSafeLocalDeleteDest(dest string) (bool, error) {
wd, err := os.Getwd()
if err != nil {
return false, errors.Wrap(err, "failed to get current working directory")
}
wd, err = resolveOutputPath(wd)
if err != nil {
return false, errors.Wrap(err, "failed to evaluate current working directory")
}
dest, err = resolveOutputPath(dest)
if err != nil {
return false, errors.Wrapf(err, "failed to evaluate local output destination %q", dest)
}
rel, err := filepath.Rel(wd, dest)
if err != nil {
return false, nil
}
if rel == "." || rel == ".." || filepath.IsAbs(rel) || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
return false, nil
}
return true, nil
}
func resolveOutputPath(p string) (string, error) {
p, rest, err := osutil.EvaluateToExistingPath(p)
if err != nil {
return "", err
}
p, err = osutil.GetLongPathName(p)
if err != nil {
return "", err
}
if rest != "" {
p = filepath.Join(p, rest)
}
return filepath.Clean(p), nil
}
func wrapWriteCloser(wc io.WriteCloser) func(map[string]string) (io.WriteCloser, error) {
return func(map[string]string) (io.WriteCloser, error) {
return wc, nil