ONNX
security
malware-detection
File size: 2,555 Bytes
d2507b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
}