Skip to content

Commit 11671f5

Browse files
committed
chore: add more comment
1 parent 762918e commit 11671f5

File tree

1 file changed

+32
-4
lines changed
  • pkg/plugin_packager/decoder

1 file changed

+32
-4
lines changed

pkg/plugin_packager/decoder/fs.go

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,35 @@ func (d *FSPluginDecoder) Close() error {
125125
return nil
126126
}
127127

128-
func ensureUnderRoot(root, name string) (string, error) {
128+
// secureResolvePath securely resolves a path relative to a root directory.
129+
//
130+
// This function prevents path traversal attacks by validating that the resolved
131+
// path stays within the root directory. It handles both forward slashes and
132+
// OS-specific path separators, making it safe for cross-platform use.
133+
//
134+
// Parameters:
135+
// - root: The base directory path that acts as a security boundary
136+
// - name: A relative path (potentially with forward slashes) to resolve
137+
//
138+
// Returns:
139+
// - The absolute, resolved path if it stays within root
140+
// - An error if the path attempts to escape the root directory
141+
//
142+
// Security: This prevents attacks like "../../../etc/passwd" by computing
143+
// the relative path from root to the target and rejecting any path that
144+
// starts with ".." (indicating an escape attempt).
145+
//
146+
// Algorithm:
147+
// 1. Join root with name, converting forward slashes to OS format
148+
// 2. Clean the joined path to resolve any "." or ".." segments
149+
// 3. Convert both root and target to absolute paths
150+
// 4. Compute the relative path from root to target
151+
// 5. If relative path starts with "..", reject as path traversal
152+
//
153+
// Example:
154+
// root="/app/plugins", name="config/settings.yaml" -> "/app/plugins/config/settings.yaml"
155+
// root="/app/plugins", name="../../../etc/passwd" -> error (path traversal)
156+
func secureResolvePath(root, name string) (string, error) {
129157
p := filepath.Join(root, filepath.FromSlash(name))
130158
clean := filepath.Clean(p)
131159
rootAbs, err := filepath.Abs(root)
@@ -150,15 +178,15 @@ func ensureUnderRoot(root, name string) (string, error) {
150178
}
151179

152180
func (d *FSPluginDecoder) Stat(filename string) (fs.FileInfo, error) {
153-
abs, err := ensureUnderRoot(d.root, filename)
181+
abs, err := secureResolvePath(d.root, filename)
154182
if err != nil {
155183
return nil, err
156184
}
157185
return os.Stat(abs)
158186
}
159187

160188
func (d *FSPluginDecoder) ReadFile(filename string) ([]byte, error) {
161-
abs, err := ensureUnderRoot(d.root, filename)
189+
abs, err := secureResolvePath(d.root, filename)
162190
if err != nil {
163191
return nil, err
164192
}
@@ -190,7 +218,7 @@ func (d *FSPluginDecoder) ReadDir(dirname string) ([]string, error) {
190218
}
191219

192220
func (d *FSPluginDecoder) FileReader(filename string) (io.ReadCloser, error) {
193-
abs, err := ensureUnderRoot(d.root, filename)
221+
abs, err := secureResolvePath(d.root, filename)
194222
if err != nil {
195223
return nil, err
196224
}

0 commit comments

Comments
 (0)