io

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Mar 24, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package io provides guarded file I/O wrappers for ctx.

What these functions guard against

All Safe* functions apply two checks before touching the filesystem:

  • Path cleaning: filepath.Clean removes redundant separators, dot segments, and trailing slashes.
  • System prefix rejection: the resolved absolute path is checked against a deny list of system directories (/bin, /etc, /proc, /sys, /dev, /boot, /lib, /sbin, /usr/bin, /usr/lib, /usr/sbin, and the filesystem root itself). Any match returns an error before the underlying syscall executes.

SafeReadFile additionally enforces containment: the resolved path must stay within the provided base directory.

What these functions do NOT guard against

  • Symlink attacks: a cleaned path that passes the prefix check could still resolve to a different location through a symlink in a parent directory. Use [validation.CheckSymlinks] separately when the directory tree is untrusted.
  • Race conditions (TOCTOU): the check and the I/O are not atomic. A malicious actor with write access to the parent directory could swap a path between validation and use.
  • Permission escalation: these wrappers run with the calling process's permissions. They do not drop privileges.
  • Content validation: the wrappers check where data is read from or written to, not what the data contains.
  • Windows paths: the deny list uses Unix prefixes. On Windows, the prefix check is effectively a no-op.

Assumptions

Callers are expected to provide paths that are already logically correct (e.g., constructed from known config constants or user input that has been validated for format). These wrappers are a safety net against accidental system directory access, not a substitute for input validation at the application boundary.

When to use which function

  • SafeReadFile: path is base + filename (boundary-checked read)
  • SafeReadUserFile: single path from any source (deny-list read)
  • SafeOpenUserFile: single path, need a file handle (deny-list open)
  • SafeWriteFile: single path (deny-list write)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SafeAppendFile

func SafeAppendFile(path string, perm os.FileMode) (*os.File, error)

SafeAppendFile opens a file for appending after cleaning the path and rejecting system directory prefixes. Creates the file if it does not exist.

Parameters:

  • path: file path to open
  • perm: file permission bits used when creating the file

Returns:

  • *os.File: open file handle in append mode (caller must close)
  • error: non-nil on validation or open failure

func SafeCreateFile

func SafeCreateFile(path string, perm os.FileMode) (*os.File, error)

SafeCreateFile creates a new file for writing after cleaning the path and rejecting system directory prefixes. If the file already exists it is truncated.

Parameters:

  • path: file path to create
  • perm: file permission bits

Returns:

  • *os.File: open file handle (caller must close)
  • error: non-nil on validation or create failure

func SafeOpenUserFile

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

SafeOpenUserFile opens a file for reading after cleaning the path and rejecting system directory prefixes.

Parameters:

  • path: file path to open

Returns:

  • *os.File: open file handle (caller must close)
  • error: non-nil on validation or open failure

func SafePost

func SafePost(
	rawURL, contentType string, body []byte, timeout time.Duration,
) (*http.Response, error)

SafePost sends an HTTP POST with the given content type and body.

Designed for static endpoint URLs that originate from trusted, user-configured sources (e.g., webhook URLs stored in AES-256-GCM encrypted storage). Centralizes gosec suppression so callers don't each need their own nolint pragma.

Protections applied:

  • Scheme validation: rejects everything except http and https, preventing file://, gopher://, and other protocol smuggling.
  • Redirect cap: follows at most 3 redirects (Go default is 10). Limits open-redirect abuse where a trusted URL bounces to an unintended destination.
  • Caller-specified timeout: bounds total request duration including redirects.

Threats explicitly not mitigated (and why that is acceptable):

  • SSRF to private IPs: the URL is a static, user-configured endpoint (not attacker-controlled input). Blocking RFC 1918 ranges would break legitimate local webhook receivers.
  • Response body size: callers are fire-and-forget (close body immediately), so unbounded reads are not a concern.
  • TLS certificate pinning: the endpoint is user-chosen; standard system CA validation is appropriate.

Parameters:

  • rawURL: destination endpoint (trusted, user-configured origin)
  • contentType: MIME type for the Content-Type header
  • body: request payload
  • timeout: per-request timeout (includes redirect hops)

Returns:

  • *http.Response: the HTTP response (caller must close Body)
  • error: on scheme validation failure, redirect cap, or HTTP error

func SafeReadFile

func SafeReadFile(baseDir, filename string) ([]byte, error)

SafeReadFile resolves filename within baseDir, verifies the result stays within the base directory boundary, and reads the file content.

Unlike SafeReadUserFile, this function enforces containment: the resolved path must remain under baseDir. Use it when the path is constructed from a trusted base and a filename component.

Parameters:

  • baseDir: trusted root directory
  • filename: file name (or relative path) to join and validate

Returns:

  • []byte: file content
  • error: non-nil if resolution fails, path escapes baseDir, or read fails

func SafeReadUserFile

func SafeReadUserFile(path string) ([]byte, error)

SafeReadUserFile reads a file after cleaning the path and rejecting system directory prefixes.

Parameters:

  • path: file path to read

Returns:

  • []byte: file content
  • error: non-nil on validation or read failure

func SafeWriteFile

func SafeWriteFile(path string, data []byte, perm os.FileMode) error

SafeWriteFile writes data to a file after cleaning the path and rejecting system directory prefixes.

Parameters:

  • path: file path to write
  • data: content to write
  • perm: file permission bits

Returns:

  • error: non-nil on validation or write failure

func TouchFile

func TouchFile(path string)

TouchFile creates or updates an empty marker file. Best-effort: errors are silently ignored. Used for throttle markers and one-shot flags in state directories.

Parameters:

  • path: absolute file path to touch

Types

This section is empty.

Jump to

Keyboard shortcuts

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