Expand description
Shell command lexing and the registered shell-allowlist gate.
The lexical layer (lexer, heredocs, tokenizer, compound and case constructs,
PowerShell statements) and the security mode live here in the Engine. The
allowlist POLICY (enforcement, approval, self-reconfiguration and side-door
checks) lives above the Engine in crates/lean-ctx-shell-policy (lib
lean_ctx_shell_policy): an edit there re-checks that crate, not the Engine.
The Engine’s own callers reach the policy through register_gate, which the
policy crate installs; without a registration every check fails closed.
Structs§
- Shell
Gate - The shell-allowlist policy as the Engine sees it.
Enums§
- Dialect
- The shell that actually executes the checked line. The check cannot read
this from the process:
ctx_executealways runsbash -con Unix and the hook for the Bash tool hands the line to bash, whatever shell this process resolves, while the PowerShell tool runs PowerShell. - Shell
Security - Active shell-security posture. Order is least → most permissive only for readability; do not rely on ordinal values.
Constants§
- MAX_
VALIDATED_ COMMAND_ BYTES - Longest command the gate validates; a longer one is refused in
enforcemode. Every check re-scans the line, and a hook that runs out of time fails open.
Functions§
- check_
registered - Check
commandagainst the registered policy. Fails closed (refuses) when no policy is registered, so a binary that forgot the registration can never run unchecked commands. - contains_
double_ semicolon - Quote-aware scan for a
;;terminator (thecasearm separator). - expand_
to_ leaf_ segments - Expand a (possibly compound) command into the list of simple-command leaves
that must each satisfy the allowlist. This is what makes
for … do CMD; done,if COND; then CMD; fi,while …; do CMD; doneand balanced( CMD )subshells usable in restricted mode without weakening deny-by-default: every leaf is still validated, headers/terminators contribute nothing, and any form this conservative walker cannot prove safe (case/esac,;;, a subshell with trailing content, deep nesting) is rejected — it over-blocks, never under-blocks. - find_
shell_ word - Return the first standalone unquoted shell word
wordat or afterstart. - gate_
registered - Whether a policy gate is installed.
- heredoc_
delims - The delimiters of the heredoc operators in
line, in source order (only quoted ones withquoted_only). A<<inside quotes,${…}or arithmetic is no operator; a<<<here-string has no body. - read_
heredoc_ delim - Parse a heredoc delimiter token starting at
start, returning its bare name (quotes/escapes removed), whether any part was quoted, and the index just past the token.Nonewhen no delimiter is present. - register_
gate - Install the policy gate. The first registration wins and is never replaced:
returns
falsewhen a gate was already registered, so the caller can refuse to start instead of running under a gate it did not install. - rewrite_
case_ constructs - Replace each
caseconstruct with all of its arm bodies. Pattern labels select which body runs, but they are not commands and must not enter the allowlist walk. Including every body preserves deny-by-default validation: every command that could execute for any pattern must be allowlisted. - strip_
all_ heredoc_ bodies - Like
strip_quoted_heredoc_bodiesbut strips bodies for all heredocs (quoted and unquoted delimiters). Use for checks that must never interpret heredoc body content as commands or redirects (#931). - strip_
for_ analysis commandwithout heredoc bodies (only quoted ones withquoted_only) and, withcomments, without comments — in one lexer pass over the raw text, so neither strip can misread what the other one removed.- warn_
only_ reason_ registered - The warn-only reason through the registered policy (the message itself when none is registered).
- with_
dialect - Runs
fwith the allowlist reading the line for the shell that will execute it, instead of the one this process resolves.