rootfs

package
v1.260819.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package rootfs provides rooted filesystem operations for paths that are not fully trusted, such as filenames, directory components, or manifest entries that come from a repository checkout or a remote API response.

Every operation is anchored to a trusted root chosen by the operator (for example a --out-dir flag, a manifest directory, or the resolved .asc directory). Paths are validated lexically so absolute paths, volume or UNC-style changes, and parent traversal are rejected, and filesystem access refuses to follow symlinks for any component below the root. Writes stage through unpredictable, exclusive, no-follow temporary files so a pre-created symlink cannot redirect them.

Roots created with AllowingInternalSymlinks relax only the parent-component rule, accepting a symlinked directory whose target stays inside the root; a symlinked final component is always refused.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrEscapesRoot reports a path that does not stay beneath the trusted root.
	ErrEscapesRoot = errors.New("path escapes trusted root")
	// ErrSymlink reports a path component that is a symlink below the trusted root.
	ErrSymlink = errors.New("refusing to follow symlink")
)

Functions

func OpenFile added in v1.260816.0

func OpenFile(path string) (*os.File, error)

OpenFile opens an existing regular file through a rooted traversal. Paths below the current working directory or OS temporary directory use that trusted anchor; other paths use their filesystem root. Unlike a final-component O_NOFOLLOW open, this rejects symlinks in parent components below the selected root.

func ValidateRelative

func ValidateRelative(name string) error

ValidateRelative reports whether name is safe to join onto a trusted root. Both Unix and Windows separator conventions are considered so a repository can not smuggle a drive-relative, UNC-style, or backslash-traversing path past validation on a different host platform.

func ValidateRelativeAllowingTraversal

func ValidateRelativeAllowingTraversal(name string) error

ValidateRelativeAllowingTraversal rejects absolute, drive-relative and UNC-style paths but permits ".." segments, for callers that resolve a path against a base directory below the root and then confirm containment of the joined result with Resolve.

Types

type Root

type Root struct {
	// contains filtered or unexported fields
}

Root is a trusted directory anchor for rooted filesystem operations.

func New

func New(path string) (Root, error)

New returns a Root anchored at path. The root itself is operator-selected and may live outside the current repository; only paths below it are constrained.

func (r Root) AllowingInternalSymlinks() Root

AllowingInternalSymlinks returns a copy of the root that accepts a symlinked directory component below the root when that component resolves back inside the root, and still rejects one that escapes.

Use it only where symlinked directories inside the root are an established, supported layout. A symlinked final component is still refused.

func (Root) AppendFile

func (r Root) AppendFile(name string, data []byte, perm os.FileMode) error

AppendFile appends data to a file beneath the root, creating it when missing, without following a final or parent symlink.

func (Root) CheckContained

func (r Root) CheckContained(name string) error

CheckContained verifies that name stays beneath the root and that neither its parent components nor its final component is a symlink below the root.

func (Root) CheckCreateNewFile added in v1.260816.0

func (r Root) CheckCreateNewFile(name string) error

CheckCreateNewFile performs the non-mutating checks required before CreateNewFile publishes a destination. Missing parents are accepted because the eventual rooted write creates them; existing files and symlinks are not.

func (Root) CheckDirectoryWritable added in v1.260816.0

func (r Root) CheckDirectoryWritable(name string, perm os.FileMode) error

CheckDirectoryWritable verifies that a temporary regular file can be created and removed within an existing directory beneath the root.

func (Root) CheckFileParent added in v1.260816.0

func (r Root) CheckFileParent(name string) error

CheckFileParent validates a future file path and all existing parent components without requiring the final destination name to be absent.

func (Root) CheckParents

func (r Root) CheckParents(name string) error

CheckParents verifies that name stays beneath the root and that every component below the root leading to it is acceptable under the root's symlink policy. The final component is not inspected.

func (Root) CheckWriteFilePreservingMode

func (r Root) CheckWriteFilePreservingMode(name string) error

CheckWriteFilePreservingMode performs the non-mutating checks required before WriteFilePreservingMode replaces an existing file. Missing destinations are accepted; callers can use this to preflight a multi-file plan before its first write.

func (Root) Close added in v1.260816.0

func (r Root) Close() error

Close releases the selected directory descriptor shared by this Root and all of its copies. Close is idempotent; no copied Root may be used afterward.

func (Root) ContainsAnchoredPath added in v1.260816.0

func (r Root) ContainsAnchoredPath(path string, anchored *os.Root) (bool, error)

ContainsAnchoredPath reports whether an already-open directory is within this root. The lexical path must still resolve to the supplied directory identity; replacements between anchoring and comparison fail closed.

func (Root) ContainsPath added in v1.260816.0

func (r Root) ContainsPath(path string) (bool, error)

ContainsPath reports whether path resolves within the directory identity selected by New. It verifies that the retained root is still reachable at its selected physical path before comparing prospective paths, so replacing the root after selection fails closed.

func (Root) CreateNewFile

func (r Root) CreateNewFile(name string, data []byte, perm os.FileMode) error

CreateNewFile writes data to a new file beneath the root and fails when the destination already exists. It prefers atomic no-replace publication, then falls back to rooted, no-follow O_EXCL creation when the filesystem does not support atomic no-replace rename.

func (Root) CreateNewFileAtomic added in v1.260816.0

func (r Root) CreateNewFileAtomic(name string, data []byte, perm os.FileMode) error

CreateNewFileAtomic atomically publishes complete data as a new file beneath the root. It returns ErrRenameNoReplaceUnsupported instead of falling back when the filesystem cannot provide atomic no-replace rename semantics.

func (Root) CreateNewFrom added in v1.260816.0

func (r Root) CreateNewFrom(name string, reader io.Reader, perm os.FileMode) (int64, error)

CreateNewFrom atomically publishes reader's complete contents as a new file beneath the root. It stages an unpredictable no-follow file in the same directory, syncs and closes it, then uses an atomic no-replace rename. A read, write, sync, close, or publish failure leaves an existing destination intact.

func (Root) MkdirAll

func (r Root) MkdirAll(name string, perm os.FileMode) error

MkdirAll creates name and any missing parents beneath the root, rejecting any existing component that is a symlink or not a directory.

func (Root) OpenDir added in v1.260816.0

func (r Root) OpenDir(name string) (*os.File, error)

OpenDir opens an existing directory beneath the root without following symlinks in the final component or in any component below the root.

func (Root) OpenFile

func (r Root) OpenFile(name string) (*os.File, error)

OpenFile opens an existing regular file beneath the root without following symlinks in the final component or in any component below the root.

func (Root) OpenRoot added in v1.260816.0

func (r Root) OpenRoot() (*os.Root, error)

OpenRoot opens the trusted root without following symlinks introduced after New selected it. New records the physical target of a pre-existing trusted symlink layout, while later path substitutions cannot change the selected directory identity. Every physical component and the final root are reopened from parent directory handles.

func (Root) Path

func (r Root) Path() string

Path returns the absolute trusted root path.

func (Root) ReadFile

func (r Root) ReadFile(name string) ([]byte, error)

ReadFile reads a regular file beneath the root without following symlinks.

func (Root) ReadFileLimited added in v1.260816.0

func (r Root) ReadFileLimited(name string, limit int64) ([]byte, error)

ReadFileLimited reads at most limit bytes from a regular file beneath the root. It rejects, rather than truncates, files that exceed the limit.

func (Root) ReadFileOptional

func (r Root) ReadFileOptional(name string) ([]byte, bool, error)

ReadFileOptional reads a regular file beneath the root and reports whether it exists. A missing file is not an error; a symlinked path still is.

func (Root) Resolve

func (r Root) Resolve(name string) (string, error)

Resolve validates name and returns its absolute path beneath the root. name may be relative to the root or an absolute path that is already inside it.

func (r Root) ResolveContainedFinalSymlink(name string) (string, error)

ResolveContainedFinalSymlink resolves a final symlink only when its physical target remains beneath this root. The returned name is relative to the root and contains no symlink components, so callers can perform the actual I/O through rooted no-follow operations without reopening the link.

func (Root) WriteFile

func (r Root) WriteFile(name string, data []byte, perm os.FileMode) error

WriteFile atomically creates or replaces a file beneath the root.

func (Root) WriteFilePreservingMode

func (r Root) WriteFilePreservingMode(name string, data []byte, perm os.FileMode) error

WriteFilePreservingMode atomically creates or replaces a regular file beneath the root. Existing files retain supported ownership, permission, ACL, and extended-attribute metadata without mutating aliases outside the rooted path. Where the platform exposes link counts, multiply linked files are refused rather than silently changing hard-link semantics. New files use perm subject to the process umask.

func (Root) WriteFrom

func (r Root) WriteFrom(name string, reader io.Reader, perm os.FileMode) (int64, error)

WriteFrom atomically creates or replaces a file beneath the root with the contents of reader and returns the number of bytes written.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL