executil

package
v0.21.3 Latest Latest
Warning

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

Go to latest
Published: Jun 19, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	HardMaxTimeout             = 10 * time.Minute
	HardMaxOutputBytes   int64 = 4 * 1024 * 1024 // per stream
	HardMaxCommands            = 64
	HardMaxCommandLength       = 64 * 1024 // bytes
	MinOutputBytes       int64 = 1024

	DefaultTimeout                = 60 * time.Second
	DefaultMaxOutputBytes   int64 = 256 * 1024
	DefaultMaxCommands            = 64
	DefaultMaxCommandLength       = 64 * 1024
)

Fixed, package-wide hard limits (single source of truth).

Variables

View Source
var HardBlockedCommands = func() map[string]struct{} {

	hard := []string{

		"sudo", "su",
		"rm",
		"mkfs",
		"shutdown", "reboot", "halt", "poweroff",

		"vim", "vi", "nano", "emacs", "less", "more", "top", "htop",

		"curl", "wget",
		"nc", "netcat", "ncat", "socat",
		"ssh", "scp", "sftp",
		"ftp", "tftp", "telnet",

		"invoke-webrequest", "iwr",
		"invoke-restmethod", "irm",

		"diskpart",
		"format.com",
		"del", "erase", "rmdir", "rd",
		"remove-item", "ri",
	}

	m := make(map[string]struct{}, len(hard))
	for _, c := range hard {
		m[c] = struct{}{}
	}
	return m
}()

Functions

func CommandFromArgv

func CommandFromArgv(selectedShell ShellName, argv []string) (string, error)

CommandFromArgv builds a safely-quoted command string for ShellTool (which executes via shell "-c"/"-Command").

Why this exists: ShellTool accepts command strings; without a canonical helper, wrappers duplicate quoting and can accidentally introduce injection bugs. This keeps quoting logic centralized and consistent.

Supported dialects:

  • sh-like shells (bash/zsh/sh/dash/ksh/fish): POSIX single-quote strategy

  • PowerShell (pwsh/powershell): single-quote strategy + "&" call operator prefix

  • cmd.exe: conservative external-command quoting; rejects double quotes/newlines

func EffectiveEnv

func EffectiveEnv(overrides map[string]string) ([]string, error)

EffectiveEnv returns the current process environment merged with overrides. It is equivalent to session-less ShellSession.GetEffectiveEnv.

func EffectiveEnvWithBase added in v0.14.0

func EffectiveEnvWithBase(baseEnv, overrides map[string]string) ([]string, error)

EffectiveEnvWithBase returns the current process environment merged with base env and overrides.

func EnvListValue added in v0.20.1

func EnvListValue(env []string, key string) (string, bool)

EnvListValue returns the value for key in an exec-style environment list. On Windows, key matching is case-insensitive.

func HostExec added in v0.15.0

func HostExec(ctx context.Context, args ...string) ([]byte, error)

HostExec runs a command on the host via flatpak-spawn --host and returns its stdout. Returns an error when host spawn is unavailable or the command fails.

func HostSpawnAvailable added in v0.15.0

func HostSpawnAvailable(ctx context.Context) bool

HostSpawnAvailable reports whether flatpak-spawn --host can be used to run commands on the host. Returns false when not inside Flatpak or the probe command fails. The result is cached after the first probe.

func IsFlatpak added in v0.15.0

func IsFlatpak() bool

IsFlatpak reports whether the current process runs inside a Flatpak sandbox. The result is cached after the first call.

func LookPathInEnv added in v0.20.1

func LookPathInEnv(file string, env []string) (string, error)

LookPathInEnv is like exec.LookPath, but searches PATH/PATHEXT from env. If env is nil, it falls back to exec.LookPath.

Empty PATH elements are intentionally not treated as ".". For tool execution this avoids current-directory executable hijacking.

func NormalizeBlockedCommand

func NormalizeBlockedCommand(s string) (string, error)

func PrependHostSpawn added in v0.15.0

func PrependHostSpawn(ctx context.Context, args []string) ([]string, bool)

PrependHostSpawn wraps args with a robust flatpak-spawn invocation:

--host         run on host
--watch-bus    host child is killed if the sandbox parent dies
--directory=…  set a sane cwd on host (defaults to $HOME on host)
--clear-env    do not leak sandbox env into host
--env=KEY=VAL  forward a filtered subset (PATH-related, locale, etc.)

func RejectDangerousCommand

func RejectDangerousCommand(
	cmd, shellPath string, shellName ShellName,
	blockedCommands map[string]struct{},
	enableHeuristicChecks bool,
) error

func RunManagedCombinedOutput added in v0.20.1

func RunManagedCombinedOutput(ctx context.Context, args []string, workdir string, env []string) ([]byte, error)

RunManagedCombinedOutput is like exec.Cmd.CombinedOutput, but uses the same process-tree isolation, hidden-window behavior, cancellation, and WaitDelay semantics as RunOneShellCommand.

func ValidateEnvMap

func ValidateEnvMap(m map[string]string) error

Types

type SelectedShell

type SelectedShell struct {
	Name ShellName
	Path string
}

func ResolveHostAutoShell added in v0.15.0

func ResolveHostAutoShell(ctx context.Context) (SelectedShell, bool)

ResolveHostAutoShell detects the preferred shell on the host system via flatpak-spawn --host. Falls back through $SHELL, getent, and common shell probes.

type SessionStore

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

func NewSessionStore

func NewSessionStore() *SessionStore

func (*SessionStore) Delete

func (ss *SessionStore) Delete(id string)

func (*SessionStore) Get

func (ss *SessionStore) Get(id string) (*ShellSession, bool)

func (*SessionStore) NewSession

func (ss *SessionStore) NewSession() *ShellSession

func (*SessionStore) SetMaxSessions

func (ss *SessionStore) SetMaxSessions(maxSessions int)

func (*SessionStore) SetTTL

func (ss *SessionStore) SetTTL(ttl time.Duration)

func (*SessionStore) Size

func (ss *SessionStore) Size() int

type ShellCommandExecResult

type ShellCommandExecResult struct {
	Command   string    `json:"command"`
	WorkDir   string    `json:"workDir"`
	Shell     ShellName `json:"shell"`
	ShellPath string    `json:"shellPath"`

	ExitCode   int   `json:"exitCode"`
	TimedOut   bool  `json:"timedOut"`
	DurationMS int64 `json:"durationMS"`

	Stdout string `json:"stdout"`
	Stderr string `json:"stderr"`

	StdoutTruncated bool `json:"stdoutTruncated"`
	StderrTruncated bool `json:"stderrTruncated"`
}

func RunOneCmdBatchScript added in v0.20.1

func RunOneCmdBatchScript(
	parent context.Context,
	cmdShell SelectedShell,
	scriptPath string,
	scriptArgs []string,
	workdir string,
	env []string,
	timeout time.Duration,
	maxOut int64,
) (ShellCommandExecResult, error)

RunOneCmdBatchScript executes a Windows batch script (.cmd or .bat) via cmd.exe, passing the script path and every argument as a SEPARATE argument to exec.Command rather than embedding them in a /c command string.

Background: the normal RunOneShellCommand path calls CommandFromArgv for the cmd dialect, which wraps the script path in cmd-style double-quotes ("C:\path\s.cmd"). When exec.Command (via syscall.EscapeArg) receives a string that already contains '"' it escapes them as \", producing "\"C:\path\s.cmd\"" in the raw Windows process command line. "cmd.exe" with /s strips the outer pair of double-quotes, leaving the literal \"C:\path\s.cmd\" which it cannot resolve to a file.

By passing scriptPath and scriptArgs as separate exec.Command arguments, each is handled independently by EscapeArg:

  • A path without spaces is left unchanged → cmd.exe sees it directly.
  • A path with spaces is wrapped in a single "…" → without /s, Windows condition 1 (exactly two quotes, whitespace between, points at a real executable) preserves the quotes and cmd.exe resolves the path.

Known limitation: a path-with-spaces combined with at least one arg-with-spaces produces four or more quote characters in the cmd.exe command line, causing condition 1 to fail and condition 2 (strip first/last quote) to garble the command. This edge case requires SysProcAttr.CmdLine construction to fix correctly and is left for a future change.

func RunOneShellCommand

func RunOneShellCommand(
	parent context.Context,
	sel SelectedShell,
	command string,
	workdir string,
	env []string,
	timeout time.Duration,
	maxOut int64,
) (ShellCommandExecResult, error)

type ShellName

type ShellName string
const (
	ShellNameAuto       ShellName = "auto"
	ShellNameBash       ShellName = "bash"
	ShellNameZsh        ShellName = "zsh"
	ShellNameSh         ShellName = "sh"
	ShellNameDash       ShellName = "dash"
	ShellNameKsh        ShellName = "ksh"
	ShellNameFish       ShellName = "fish"
	ShellNamePwsh       ShellName = "pwsh"
	ShellNamePowershell ShellName = "powershell"
	ShellNameCmd        ShellName = "cmd"
)

func NormalizeShellName added in v0.15.0

func NormalizeShellName(shell ShellName) (ShellName, error)

type ShellSession

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

func (*ShellSession) AddToEnv

func (sess *ShellSession) AddToEnv(additionalEnv map[string]string) error

func (*ShellSession) GetEffectiveEnv

func (sess *ShellSession) GetEffectiveEnv(overrides map[string]string) ([]string, error)

func (*ShellSession) GetEffectiveEnvWithBase added in v0.14.0

func (sess *ShellSession) GetEffectiveEnvWithBase(baseEnv, overrides map[string]string) ([]string, error)

func (*ShellSession) GetEffectiveWorkdir

func (sess *ShellSession) GetEffectiveWorkdir(inputWorkDir, defaultWorkDir string) (string, error)

func (*ShellSession) GetID

func (sess *ShellSession) GetID() string

func (*ShellSession) SetWorkDir

func (sess *ShellSession) SetWorkDir(workdir string)

Jump to

Keyboard shortcuts

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