Skip to content

Placeholders

Tokens wrapped in <...> are placeholders — special tokens that match dynamically rather than by exact string comparison.

PlaceholderDescription
<cmd>Captures the wrapped command for further rule evaluation
<opts>Absorbs zero or more flag-like tokens
<vars>Absorbs zero or more KEY=VALUE tokens
<path:name>Matches against a named list of paths

The <cmd> placeholder captures the remaining tokens as the wrapped command. The wrapped command is then evaluated against the other rules in the configuration. See Wrapped Command Recursion for details.

# sudo echo hello -> wrapped command is "echo hello"
- allow: 'sudo <cmd>'

Wrapper patterns are defined in the definitions.wrappers block and referenced by rules:

definitions:
wrappers:
- 'sudo <cmd>'
- 'xargs <opts> <cmd>'
rules:
- allow: 'echo *'
# With the wrapper definition, this also allows:
# sudo echo hello
# xargs -I{} echo hello

The <opts> placeholder absorbs zero or more flag-like tokens (tokens starting with -):

# Matches: env FOO=bar command
# Matches: env -i FOO=bar command
# Matches: env -u HOME -i FOO=bar command
- allow: 'env <opts> <vars> <cmd>'

<opts> stops consuming tokens when it encounters:

  • A token that does not start with -
  • The -- end-of-options marker

For short flags consisting of exactly - plus one ASCII letter (e.g., -n, -S), if the next token does not start with -, it is consumed as the flag’s argument:

# env -S "FOO=bar" command -> <opts> consumes "-S" and "FOO=bar"
- allow: 'env <opts> <cmd>'

The <vars> placeholder absorbs zero or more KEY=VALUE tokens — tokens that contain =:

# Matches: env command
# Matches: env FOO=bar command
# Matches: env FOO=bar BAZ=qux command
- allow: 'env <vars> <cmd>'

<vars> stops consuming tokens when it encounters a token without =.

The <path:name> placeholder matches a command argument against a named list of paths defined in the definitions.paths block.

definitions:
paths:
sensitive:
- /etc/passwd
- /etc/shadow
- /etc/sudoers
config:
- /etc/nginx/nginx.conf
- /etc/hosts

Reference a path list with <path:name>:

rules:
- deny: 'cat <path:sensitive>'
- deny: 'rm <path:sensitive>'
- allow: 'cat <path:config>'
CommandRuleResult
cat /etc/passwddeny: "cat <path:sensitive>"Denied
cat /etc/hostsallow: "cat <path:config>"Allowed
rm /etc/shadowdeny: "rm <path:sensitive>"Denied

Paths are normalized before comparison. The following path components are resolved:

  • . (current directory) is removed
  • .. (parent directory) is resolved
definitions:
paths:
sensitive:
- /etc/passwd
CommandMatches <path:sensitive>
cat /etc/passwdYes
cat /etc/./passwdYes (. removed)
cat /tmp/../etc/passwdYes (.. resolved)

This prevents bypassing path rules through path manipulation.

If a pattern references a path name that is not defined in definitions.paths, the pattern never matches:

# If "sensitive" is not defined, this rule has no effect
- deny: 'cat <path:sensitive>'

Placeholders can be combined to handle complex wrapper patterns:

definitions:
wrappers:
# Handles: env [-i] [-u NAME] [KEY=VALUE...] command [args...]
- 'env <opts> <vars> <cmd>'
# Handles: sudo [-u user] command [args...]
- 'sudo <opts> <cmd>'
# Handles: xargs [flags...] command [args...]
- 'xargs <opts> <cmd>'
# Handles: find [args...] -exec|-execdir|-ok|-okdir command [args...] \;|+
- "find * -exec|-execdir|-ok|-okdir <cmd> \\;|+"
  • <cmd> captures one or more tokens; it tries all possible split points to find a valid wrapped command
  • Optional groups and path references are not supported inside wrapper patterns