Documentation
¶
Overview ¶
Package cmdrun centralizes whitelisted subprocess invocation for governance and verify helpers (gocell validate / gocell check / golangci-lint runner / archtest tooling). Callers funnel through Run / RunWith so the gosec G204 path-scoped exemption lives at a single audit point and tool-path validation is enforced via the ValidatedTool newtype's unexported field (NewTool runs exec.LookPath + filepath.Abs + filepath.Clean).
cmdrun is not the only subprocess entry point in the repo — tests in tools/generatedverify and examples/ssobff invoke exec.Command directly for `git`, `go build`, and the produced binary. Those sites are kept outside cmdrun because they exercise binary names that are constant strings under test control, not the LookPath-mediated whitelist that cmdrun guards. Production callers (anything outside *_test.go and outside examples/) must funnel through cmdrun.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Run ¶
Run executes the validated tool with args using ctx and returns combined stdout+stderr. It inherits the parent process working directory and a denylist-cleaned copy of the parent environment.
func RunWith ¶
func RunWith(ctx context.Context, t ValidatedTool, opts RunOptions, args ...string) ([]byte, error)
RunWith executes the validated tool with args. By default it inherits a denylist-cleaned copy of os.Environ; ExtraEnv is then applied additively so callers must explicitly opt sensitive values back in when a subprocess genuinely needs them. Combined stdout+stderr is returned.
On Unix, RunWith starts the subprocess in its own process group (Setpgid) so that ctx cancellation kills the entire process tree, not just the direct child. This prevents orphaned grandchild processes (e.g. test subprocesses spawned by `go test`) from continuing to run after ctx is canceled.
ValidatedTool.path is exec.LookPath-resolved at NewTool construction; args are caller-controlled whitelisted invocations from governance / verify helpers, never user input. gosec G204 on the variable binary path is a false positive in this context — addressed by the .golangci.yml path-scoped exemption rather than reshaping the invocation. See package doc for callers that bypass cmdrun (tests).
Types ¶
type RunOptions ¶
type RunOptions struct {
// Dir optionally sets the subprocess working directory. Empty means inherit.
Dir string
// ExtraEnv appends to, or overrides, the cleaned parent environment. Nil
// and empty slices do not clear the inherited environment.
ExtraEnv []string
}
RunOptions controls subprocess execution for RunWith.
type ValidatedTool ¶
type ValidatedTool struct {
// contains filtered or unexported fields
}
ValidatedTool wraps a tool binary invocation path with two enforced invariants:
- The path is exec.LookPath-resolved (the binary exists at construction time, not at first Run — caller can fail-fast at startup).
- The path is absolute (filepath.IsAbs == true). LookPath returns a bare name when name has no path separators and PATH lookup succeeds, or returns name as-is when name contains a separator. NewTool always normalizes to filepath.Abs so the resolved binary cannot be hijacked by later cwd changes or by a writable PATH directory inserted into PATH after construction.
The unexported `path` field forces normal API construction through NewTool — package consumers cannot legally produce a non-empty path bypassing the invariants. Zero values (constructed via reflect/unsafe or embedded literal `ValidatedTool{}`) carry an empty path, which makes Run fail-closed at exec.CommandContext with a "no such file or directory" error rather than panicking or executing arbitrary code.
func NewTool ¶
func NewTool(name string) (ValidatedTool, error)
NewTool resolves name via exec.LookPath, normalizes to an absolute filepath.Clean'd form, and wraps the result in a ValidatedTool. Returns an error wrapping the LookPath failure when name cannot be found in PATH, or filepath.Abs failure (extremely rare — only when getwd fails).
func (ValidatedTool) Dir ¶
func (t ValidatedTool) Dir() string
Dir returns the directory containing the tool binary. Callers use this for toolchain-locality concerns (e.g., prepending to PATH so subprocess helpers resolve to the same toolchain that owns the binary).