Skip to content

Commit 68a8f28

Browse files
committed
feat: skip symlinks in model distribution to prevent directory traversal attacks
1 parent 7a65e5b commit 68a8f28

File tree

1 file changed

+4
-32
lines changed

1 file changed

+4
-32
lines changed

pkg/distribution/internal/bundle/unpack.go

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -300,38 +300,10 @@ func extractTarArchive(archivePath, destDir string) error {
300300
}
301301

302302
case tar.TypeSymlink:
303-
// Handle symlinks safely - validate where the symlink will actually point after resolution.
304-
// Symlinks are resolved relative to their parent directory, not the base directory.
305-
// We must validate the final resolved absolute path to prevent directory traversal.
306-
307-
// Calculate the symlink's parent directory (where it will be created)
308-
symlinkParent := filepath.Dir(absTarget)
309-
310-
// Resolve the symlink target relative to the symlink's parent directory
311-
// This gives us where the symlink will actually point when followed
312-
resolvedTarget := filepath.Join(symlinkParent, header.Linkname)
313-
314-
// Get the absolute path of where the symlink will point
315-
absResolvedTarget, err := filepath.Abs(resolvedTarget)
316-
if err != nil {
317-
return fmt.Errorf("resolve symlink target for %q: %w", header.Name, err)
318-
}
319-
320-
// Validate that the resolved absolute path stays within the destination directory
321-
rel, err := filepath.Rel(absDestDir, absResolvedTarget)
322-
if err != nil {
323-
return fmt.Errorf("validate symlink target for %q: %w", header.Name, err)
324-
}
325-
326-
// Use filepath.IsLocal() to ensure the symlink target doesn't escape the base directory
327-
if !filepath.IsLocal(rel) {
328-
return fmt.Errorf("invalid symlink %q: target %q",
329-
header.Name, header.Linkname)
330-
}
331-
332-
if err := os.Symlink(header.Linkname, absTarget); err != nil {
333-
return fmt.Errorf("create symlink %s: %w", absTarget, err)
334-
}
303+
// Skip symlinks - not needed for model distribution
304+
// Symlinks could enable directory traversal attacks even with validation
305+
// Model archives should only contain regular files and directories
306+
continue
335307

336308
default:
337309
// Skip other types (block devices, char devices, FIFOs, etc.)

0 commit comments

Comments
 (0)