security

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Jul 7, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package security implements atago's security model: masking secret values in reports and logs, and the safe defaults enabled by --ci.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckHost

func CheckHost(allow []string, hostport string) error

CheckHost reports whether hostport (a "host" or "host:port") is permitted by the allowlist, returning a *PolicyError otherwise. An empty allowlist means no network policy is configured and everything is permitted.

func ReadFileNoFollow added in v0.5.1

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

ReadFileNoFollow reads path but refuses to follow a symlink planted at the leaf. Lexical containment (ResolveWorkdirPath/ResolveSpecPath) proves path is inside its root, but the untrusted program under test may have replaced the leaf with a link pointing outside the root — os.ReadFile would follow it and disclose an arbitrary host file (issue #16). An existing symlink is rejected outright, mirroring WriteFileNoFollow's guard on the write path so every path-taking feature enforces the same rule instead of a plain, link-following os.ReadFile.

func ResolveSpecPath

func ResolveSpecPath(field, specDir, p string) (string, error)

ResolveSpecPath resolves a spec-scoped path (currently snapshot paths) and guarantees it stays inside the spec directory. field names the spec field for a clear error.

func ResolveWorkdirPath

func ResolveWorkdirPath(field, workdir, p string) (string, error)

ResolveWorkdirPath resolves a workdir-scoped path and guarantees it stays inside the scenario workdir. field names the spec field for a clear error.

func WithinRoot

func WithinRoot(root, resolved string) bool

WithinRoot reports whether resolved lies inside root (root itself counts). Callers that resolve a path with non-default semantics — a symlink target resolved against the link's own directory, say — can reuse this single containment test instead of re-deriving prefix logic. It uses filepath.Rel so a relative root such as "." (a spec loaded by a bare filename) is handled the same as an absolute one, comparing whole path components rather than raw string prefixes.

func WriteFileNoFollow added in v0.5.1

func WriteFileNoFollow(dest string, data []byte, perm os.FileMode) error

WriteFileNoFollow writes data to dest without following a symlink planted at dest. Lexical containment proves dest is inside its root, but the untrusted program under test may have created a link there pointing outside the root; following it on write would escape containment and clobber a host file (TOCTOU, issue #16). An existing symlink is rejected outright; an existing regular file is removed and re-created with O_EXCL so a link planted in the race is never written through (O_EXCL fails atomically on any existing path). This is portable — unlike O_NOFOLLOW, which is not available on all platforms.

Types

type Masker

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

Masker replaces known secret values with a fixed placeholder.

func NewMasker

func NewMasker(values []string) *Masker

NewMasker builds a Masker from literal secret values. Empty or very short values are ignored.

func NewMaskerForSpec

func NewMaskerForSpec(s *spec.Spec) *Masker

NewMaskerForSpec collects secret values for a spec from the process environment and from per-step env overrides of the names listed under `secrets:`.

func (*Masker) Empty

func (m *Masker) Empty() bool

Empty reports whether the masker has nothing to mask.

func (*Masker) Mask

func (m *Masker) Mask(s string) string

Mask replaces every known secret value in s with "***". It marks the byte ranges of every secret occurrence over the ORIGINAL string in one pass, then collapses each maximal covered run to a single placeholder. Scanning the original (rather than a sequence of ReplaceAll that mutates s) is what keeps two overlapping secrets — one ending with the bytes the next begins with, e.g. "abcXYZ" and "XYZdef" in "abcXYZdef" — both masked; a sequential replace would consume the shared bytes and leak the second secret's tail.

func (*Masker) MaskBytes

func (m *Masker) MaskBytes(b []byte) []byte

MaskBytes is Mask for byte slices, returning the input unchanged when there is nothing to mask.

type PolicyError

type PolicyError struct {
	Host  string
	Allow []string
}

PolicyError reports a network egress that permissions.network.allow does not permit. It is returned by CheckHost and lets the engine flag a security-policy violation for grpc/ssh steps, mirroring the HTTP runner.

func (*PolicyError) Error

func (e *PolicyError) Error() string

Jump to

Keyboard shortcuts

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