package compactscan import ( "errors" "io/fs" "os" "path/filepath" ) // preflightMaxFiles mirrors the whole-bundle scanner's discovery bound. It // counts SKILL.md as well as siblings, so an accepted tree always fits within // the scanner without producing a partial-scan note. const preflightMaxFiles = 4096 // preflightPackage validates the complete package tree without reading member // content. In particular, this runs before bundle.Scan, whose analysis path is // intentionally willing to inspect symlink targets. Compact scoring is // stricter: no link or special file may be opened at all. func preflightPackage(rootPath string) error { rootInfo, err := os.Lstat(rootPath) if err != nil { return errors.New("inspect package root") } if rootInfo.Mode()&os.ModeSymlink != 0 || !rootInfo.IsDir() { return errors.New("package root is not an unlinked directory") } root, err := os.OpenRoot(rootPath) if err != nil { return errors.New("open package root") } defer root.Close() fileCount := 0 err = filepath.WalkDir(rootPath, func(path string, entry fs.DirEntry, walkErr error) error { if walkErr != nil { return errors.New("walk package tree") } if path == rootPath { return nil } rel, err := filepath.Rel(rootPath, path) if err != nil || rel == "." || filepath.IsAbs(rel) || hasTraversal(rel) { return errors.New("package tree contains a non-canonical member") } info, err := root.Lstat(rel) if err != nil { return errors.New("package member changed during preflight") } if info.Mode()&os.ModeSymlink != 0 { return errors.New("package tree contains a symlink") } if info.IsDir() { return nil } if !info.Mode().IsRegular() { return errors.New("package tree contains a non-regular file") } fileCount++ if fileCount > preflightMaxFiles { return errors.New("package tree exceeds the file limit") } file, err := openPreflightFile(root, rel) if err != nil { return errors.New("open package member during preflight") } opened, statErr := file.Stat() if statErr != nil { _ = file.Close() return errors.New("stat package member during preflight") } links, linkErr := openedHardLinkCount(file, opened) closeErr := file.Close() if linkErr != nil || closeErr != nil || !opened.Mode().IsRegular() || !os.SameFile(info, opened) { return errors.New("package member changed during preflight") } if links != 1 { return errors.New("package tree contains a hard-linked file") } return nil }) if err != nil { return err } return nil }