Security Profiles
Profile System
Section titled “Profile System”Each session runs under a security profile that controls capabilities, resource limits, filesystem access, network policy, and environment enforcement. Profiles are defined as .profile files in ~/.lash/profiles/.
Built-in Profiles
Section titled “Built-in Profiles”| Profile | Description |
|---|---|
default | Full access. Config, other sessions, audit log, profile management. |
script | No plugins, no job control, no admin. Suitable for non-interactive scripts. |
ci | Restricted spawn via allowlist. Resource limits and env denylist. |
restricted | Minimal. No arbitrary processes, no redirects, no env mutation. |
Profile File Format
Section titled “Profile File Format”Profiles use INI-style sections. Each .profile file in ~/.lash/profiles/ defines one profile:
[profile]description = CI/CD build environment
[inherit]from = default
[process]spawn_any = falsespawn_allowlist = make, cmake, gcc, git, cargo, dubspawn_denylist = rm, dd
[filesystem]sandbox = /home/ci/buildsread_only = /usr, /libread_write = /tmpinclude_workdir = truetmpdir = session
[network]allow_hosts = github.com, *.npmjs.orgallow_ports = 443, 80block_all_others = trueenforcement = enforce
[resources]max_memory = 2Gmax_cpu_seconds = 300max_file_size = 100Mmax_processes = 64max_open_files = 256
[environment]deny = LD_PRELOAD, LD_LIBRARY_PATHforce = SANDBOX=1, CI=truemutation = truesafelist = PATH, HOME, CC, CXX
[capabilities]file_redirect = trueplugin_access = falseconfig_modify = falsesession_manage = falsejob_control_own = falseaudit_access = falseprofile_manage = falseprofile_switch = false
[monitoring]enabled = trueInheritance
Section titled “Inheritance”Profiles can inherit from another profile using the [inherit] section. Child values override parent values. Capabilities use explicit-bit tracking so only fields you set override the parent.
[inherit]from = ciProfile Commands
Section titled “Profile Commands”profile list # list all profiles and active profileprofile review <name> # show resolved settings for a profileprofile permissions [name] # show capabilities and resource limitsprofile test <name> <cmd> # dry-run: would this command be allowed?profile create <name> # create a new profile fileprofile edit <name> # open profile in $EDITORprofile reload # reload active profile from diskThe create, edit, and reload subcommands require the profileManage capability. Profile switching is handled by the audit plugin and requires the profileSwitch capability.
Capabilities
Section titled “Capabilities”| Capability | Description |
|---|---|
spawnAny | Allow spawning any process from PATH. |
spawnAllowlist | Comma-separated permitted commands (when spawnAny is false). |
spawnDenylist | Comma-separated commands that are always denied. |
fileRedirect | Allow >, >> file writes. |
fileSandbox | Restrict writes to a directory. |
envMutation | Allow modifying env vars. |
envSafelist | Comma-separated env vars that can be modified. |
envDenylist | Env vars stripped from child processes before exec. |
envForced | KEY=VALUE pairs injected into child processes. |
pluginAccess | Allow calling plugin methods. |
pluginAllowlist | Comma-separated permitted plugins. |
configModify | Allow modifying config at runtime. |
sessionManage | Allow managing other sessions (list, kill). |
jobControlOwn | Allow fg/bg/jobs for own jobs. |
jobControlOthers | Allow managing other sessions’ jobs. |
auditAccess | Allow audit commands and log access. |
profileManage | Allow creating, editing, and reloading profiles. |
profileSwitch | Allow switching the active profile. |
Resource Limits
Section titled “Resource Limits”Resource limits are enforced at the OS level on spawned processes:
| Limit | Description |
|---|---|
max_memory | Maximum memory per process (e.g. 512M, 2G). |
max_cpu_seconds | CPU time limit in seconds. |
max_file_size | Maximum file size a process can create. |
max_processes | Maximum number of child processes. |
max_open_files | Maximum open file descriptors. |
Set to 0 or omit for unlimited.
Filesystem Sandboxing
Section titled “Filesystem Sandboxing”Filesystem restrictions are enforced via Landlock (Linux) or Seatbelt (macOS) through the armor library:
sandbox— root directory for sandboxed writesread_only— paths allowed for read-only accessread_write— paths allowed for read-write accessinclude_workdir— whether the current directory is automatically added to read-write pathstmpdir = session— creates a per-session temporary directory
Network Policy
Section titled “Network Policy”Network restrictions use a transparent proxy with TLS SNI verification:
allow_hosts— hostnames or wildcard patterns (e.g.*.github.com)allow_ports— TCP ports allowed for outbound connectionsblock_all_others— deny all traffic not matching allow rulesenforcement—enforce(default) orwarn(log but allow)
On Linux, a TUN device provides transparent interception. DNS queries are intercepted to enforce hostname-level policy. TLS connections are verified by SNI to prevent IP-based bypass.
Auto-Detection
Section titled “Auto-Detection”When profile.auto_detect = true is set in ~/.lash/config, the daemon checks the session context and suggests switching to a matching profile. Dismissals are tracked per-session.
Denied Actions
Section titled “Denied Actions”When a profile denies an action, the shell returns a Problem/Suggestion error:
Problem: This session (profile: restricted) cannot run 'curl'.Suggestion: 'curl' is not in the allowlist. Switch to a different profile.