Skip to content

Audit and Profiles

lash can keep a secure log of everything that happens in your shell — every command you run, every variable you set, every session you open. This log is protected so that nobody (not even you) can secretly edit or delete entries without the system detecting it.

Think of it like a security camera for your terminal. Once recording starts, the footage is tamper-proof.

On top of that, lash has security profiles that control what a session is allowed to do. You can lock down a session so it can only run certain programs, or prevent it from writing files outside a specific folder. Profiles are enforced at the kernel level via Landlock (Linux) or Seatbelt (macOS).

Run audit init and pick a password:

audit init
Audit password: ********
Audit initialized.
Select a default profile for new sessions:
1) default - No restrictions
2) developer - Sane defaults for local development
3) ci - Locked down for CI pipelines (allowlist + network policy)
4) restricted - Minimal permissions, no network
5) untrusted - Maximum isolation, sandbox to ~/sandbox
Choice [1-5]: 2
Default profile set to: developer

That’s it. From now on, lash logs every hook event to ~/.lash/audit.log.

To verify that your audit log hasn’t been tampered with:

audit verify
Audit password: ********
Audit Report
===================================
Entries: 1247
Period: 2026-01-15T08:00:00 -> 2026-03-06T14:30:00
Status: INTACT
Events by type:
pipeline.post_execute: 489
pipeline.pre_execute: 489
session.connect: 120
session.disconnect: 118
Violations: 0

If someone (or something) modified even a single byte in the log, the status changes to TAMPERED and the violations section lists exactly which entries were affected.

Over time, the log file grows. To verify and clear it:

audit rotate
Audit password: ********
Audit log verified and deleted. Chain reset.

This verifies the entire log first. If verification fails, the log is kept intact — nothing is deleted.

Profiles control what a shell session is allowed to do. The five built-in profiles are:

ProfileWhat you can do
defaultEverything. No restrictions.
developerCurated allowlist of dev tools, write access to cwd and /tmp.
ciLocked down for CI pipelines: allowlisted toolchain, network policy enforced.
restrictedMinimal permissions: a handful of read-only utilities, no network.
untrustedMaximum isolation: sandboxed to ~/sandbox, no shells, no network.

To see your current profile:

profile
Current profile: developer

Need to do something that requires a different profile? Switch with profile <name>:

profile default
Audit password: ********
Switched to profile: default

Every profile switch requires the audit password. This prevents someone from escalating privileges without authorization.

When you’re done, switch back:

profile developer
Audit password: ********
Switched to profile: developer

If you try something your profile doesn’t allow, lash tells you exactly what went wrong:

Problem: This session (profile: restricted) cannot run 'curl'.
Suggestion: 'curl' is not in the allowlist. Switch to a less restricted profile.

The profile you picked during audit init applies to every new session. To change it later, edit ~/.lash/config:

[settings]
profile.default = developer

A good practice: use developer as the default and switch to default only when you need full access.

You can define your own profiles as *.profile files in ~/.lash/profiles/. The format is INI-style. For example, a profile that only allows build tools:

~/.lash/profiles/build.profile
[profile]
description = Build-tools-only sandbox.
[inherit]
from = profile:default
[process]
allowlist = make, cmake, ninja, gcc, g++, clang, git, cargo, dub
deny_all_others = true
[filesystem]
include_workdir = true
read_only = /usr, /lib, /lib64, /etc, /proc, /sys
read_write = /tmp
[capabilities]
file_redirect = true
env_mutation = true
plugin_access = false

Then switch to it:

profile build
Audit password: ********
Switched to profile: build

See Security Profiles for the full list of capabilities you can configure.

CommandWhat it does
audit initSet up audit logging (one-time)
audit verifyCheck the log for tampering
audit rotateVerify and clear the log
profileShow current profile
profile <name>Switch to a different profile