TermUI.TermUtils (TermUI v1.0.0)
View SourceSafe terminal command execution utilities.
This module provides secure wrappers for executing terminal-related external commands (stty, test, etc.) with the following protections:
- Absolute path resolution - Commands are executed from known-safe locations
- Timeout enforcement - All commands have configurable timeouts
- Output validation - Command output is validated against expected formats
- Argument sanitization - All arguments are validated before execution
Security Model
This module follows a defense-in-depth approach:
- Allowlist: Only known-safe commands are permitted
- Validation: All arguments are validated against expected patterns
- Timeout: Commands are terminated if they exceed time limits
- Sanitization: Output is sanitized before return
Example
# Safe stty execution with timeout
case TermUI.TermUtils.safe_stty(["-g"], timeout: 1000) do
{:ok, output} -> process_output(output)
{:error, :timeout} -> handle_timeout()
{:error, reason} -> handle_error(reason)
end
Summary
Functions
Generic safe command execution for whitelisted commands.
Executes infocmp command with safety protections.
Executes stty command with safety protections.
Executes test command with safety protections.
Validates stty -g output format.
Validates stty size output format.
Types
@type options() :: [timeout: pos_integer(), validate: (binary() -> :ok | :error)]
Command options
@type reason() :: :timeout | :command_not_found | :invalid_arguments | :not_tty | :execution_failed | :output_validation_failed | term()
Error reasons
Command execution result
Functions
Generic safe command execution for whitelisted commands.
Security
- Only whitelisted commands are permitted
- Timeout is enforced
- Command is executed with minimal privileges
Returns
{:ok, output}- Command succeeded{:error, :timeout}- Command exceeded timeout{:error, :command_not_found}- Command not in whitelist{:error, reason}- Other error
Executes infocmp command with safety protections.
infocmp is used to query terminal capability information.
Returns
{:ok, output}- Command succeeded{:error, :timeout}- Command exceeded timeout{:error, reason}- Other error
Executes stty command with safety protections.
Arguments
args- List of string arguments to pass to sttyopts- Optional keyword list::timeout- Maximum milliseconds to wait (default 5000):validate- Function to validate output (default: basic validation)
Returns
{:ok, output}- Command succeeded with validated output{:error, :timeout}- Command exceeded timeout{:error, :command_not_found}- stty not found in PATH{:error, :invalid_arguments}- Arguments failed validation{:error, :not_tty}- No controlling terminal is available{:error, reason}- Other execution error
Example
{:ok, settings} = TermUI.TermUtils.safe_stty(["-g"])
{:ok, :done} = TermUI.TermUtils.safe_stty(["raw", "-echo"])
Executes test command with safety protections.
The test command is used for terminal detection (e.g., test -t 0 to check
if stdin is a TTY).
Returns
{:ok, output}- Command succeeded{:error, :timeout}- Command exceeded timeout{:error, reason}- Other error
Example
{:ok, _} = TermUI.TermUtils.safe_test(["-t", "0"])
Validates stty -g output format.
Stty -g returns settings in format like: "speed 9600 baud; rows 24; columns 80;" This is the output we later pass to stty for restoration, so we must validate it carefully to prevent command injection.
Validates stty size output format.
Stty size returns: "rows cols" (two integers)