package pathrs

import "github.com/cyphar/filepath-securejoin/pathrs-lite"

Package pathrs (pathrs-lite) is a less complete pure Go implementation of some of the APIs provided by libpathrs.

Index

Functions

func MkdirAll

func MkdirAll(root, unsafePath string, mode os.FileMode) error

MkdirAll is a race-safe alternative to the os.MkdirAll function, where the new directory is guaranteed to be within the root directory (if an attacker can move directories from inside the root to outside the root, the created directory tree might be outside of the root but the key constraint is that at no point will we walk outside of the directory tree we are creating).

Effectively, MkdirAll(root, unsafePath, mode) is equivalent to

path, _ := securejoin.SecureJoin(root, unsafePath)
err := os.MkdirAll(path, mode)

But is much safer. The above implementation is unsafe because if an attacker can modify the filesystem tree between SecureJoin and os.MkdirAll, it is possible for MkdirAll to resolve unsafe symlink components and create directories outside of the root.

If you plan to open the directory after you have created it or want to use an open directory handle as the root, you should use MkdirAllHandle instead. This function is a wrapper around MkdirAllHandle.

func MkdirAllHandle

func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (*os.File, error)

MkdirAllHandle is equivalent to MkdirAll, except that it is safer to use in two respects:

In addition, the returned handle is obtained far more efficiently than doing a brand new lookup of unsafePath (such as with SecureJoin or openat2) after doing MkdirAll. If you intend to open the directory after creating it, you should use MkdirAllHandle.

func OpenInRoot

func OpenInRoot(root, unsafePath string) (*os.File, error)

OpenInRoot safely opens the provided unsafePath within the root. Effectively, OpenInRoot(root, unsafePath) is equivalent to

path, _ := securejoin.SecureJoin(root, unsafePath)
handle, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC)

But is much safer. The above implementation is unsafe because if an attacker can modify the filesystem tree between SecureJoin and os.OpenFile, it is possible for the returned file to be outside of the root.

Note that the returned handle is an O_PATH handle, meaning that only a very limited set of operations will work on the handle. This is done to avoid accidentally opening an untrusted file that could cause issues (such as a disconnected TTY that could cause a DoS, or some other issue). In order to use the returned handle, you can "upgrade" it to a proper handle using Reopen.

func OpenatInRoot

func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error)

OpenatInRoot is equivalent to OpenInRoot, except that the root is provided using an *os.File handle, to ensure that the correct root directory is used.

func Reopen

func Reopen(handle *os.File, flags int) (*os.File, error)

Reopen takes an *os.File handle and re-opens it through /proc/self/fd. Reopen(file, flags) is effectively equivalent to

fdPath := fmt.Sprintf("/proc/self/fd/%d", file.Fd())
os.OpenFile(fdPath, flags|unix.O_CLOEXEC)

But with some extra hardenings to ensure that we are not tricked by a maliciously-configured /proc mount. While this attack scenario is not common, in container runtimes it is possible for higher-level runtimes to be tricked into configuring an unsafe /proc that can be used to attack file operations. See CVE-2019-19921 for more details.

Source Files

doc.go mkdir.go mkdir_purego.go open.go open_purego.go

Directories

PathSynopsis
pathrs-lite/internalPackage internal contains unexported common code for filepath-securejoin.
pathrs-lite/procfsPackage procfs provides a safe API for operating on /proc on Linux.
Version
v0.6.1 (latest)
Published
Nov 19, 2025
Platform
linux/amd64
Imports
4 packages
Last checked
1 hour ago

Tools for package owners.