Description
As discussed in #714, filepath.Join is used to construct container state directory paths from user-controlled containerID input:
pkg/unikontainers/unikontainers.go New(): filepath.Join(rootDir, containerID)
pkg/unikontainers/unikontainers.go Get(): filepath.Join(rootDir, containerID)
cmd/urunc/delete.go ErrNotExist fallback: filepath.Join(rootDir, containerID)
While #726 (validateID) blocks character-based injection, filepath.Join does not protect against symlink-based path escapes. If rootDir or any component in the path is a symlink pointing outside the intended directory, filepath.Join follows it silently. securejoin.SecureJoin resolves the full path within the root boundary, refusing to escape even through symlinks.
Proposed change
Replace the three filepath.Join(rootDir, containerID) calls with securejoin.SecureJoin(rootDir, containerID) and add github.com/cyphar/filepath-securejoin as a direct dependency.
I'd be happy to work on this if it sounds good.
Description
As discussed in #714,
filepath.Joinis used to construct container state directory paths from user-controlledcontainerIDinput:pkg/unikontainers/unikontainers.goNew():filepath.Join(rootDir, containerID)pkg/unikontainers/unikontainers.goGet():filepath.Join(rootDir, containerID)cmd/urunc/delete.goErrNotExistfallback:filepath.Join(rootDir, containerID)While #726 (validateID) blocks character-based injection,
filepath.Joindoes not protect against symlink-based path escapes. IfrootDiror any component in the path is a symlink pointing outside the intended directory,filepath.Joinfollows it silently.securejoin.SecureJoinresolves the full path within the root boundary, refusing to escape even through symlinks.Proposed change
Replace the three
filepath.Join(rootDir, containerID)calls withsecurejoin.SecureJoin(rootDir, containerID)and addgithub.com/cyphar/filepath-securejoinas a direct dependency.I'd be happy to work on this if it sounds good.