feat(skill): add execline-hardening skill to workspace
Adds comprehensive execline documentation covering:
- Security properties and chain loading
- Variable management (define, importas, backtick)
- Conditionals, loops, file operations
- Comparison table vs shell
- When exec tool is unavailable (AI fallback workflow)
- Positional arguments (-sN flag)
💘 Generated with Crush
This commit is contained in:
parent
a2dd451d8c
commit
ec61020e4f
1 changed files with 273 additions and 0 deletions
273
workspace/skills/execline/SKILL.md
Normal file
273
workspace/skills/execline/SKILL.md
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
# execline-hardening Skill
|
||||
|
||||
Security hardening for agentic systems using execline instead of bash.
|
||||
|
||||
## What is execline?
|
||||
|
||||
execline is a minimal scripting language from [skarnet.org](https://skarnet.org/software/execline/) designed for security and simplicity. It uses **chain loading** - each command execs into the next one, rather than staying resident like a shell.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Debian/Ubuntu/Armbian
|
||||
apt install execline
|
||||
|
||||
# Alpine
|
||||
apk add execline
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Chain Loading
|
||||
execline uses exec() heavily - each program runs, then execs into the next one:
|
||||
```
|
||||
execlineb -c "nice -10 echo hello"
|
||||
```
|
||||
This is more efficient than spawning a shell interpreter.
|
||||
|
||||
### Whitespace is Whitespace
|
||||
Newlines, spaces, and tabs are all treated the same - they're just word separators.
|
||||
|
||||
### Blocks
|
||||
Curly braces `{ }` create blocks to group commands with their arguments:
|
||||
```
|
||||
foreground { echo hello } echo world
|
||||
```
|
||||
|
||||
## Security Properties
|
||||
|
||||
### What execline DOESN'T do:
|
||||
- **Command substitution**: `$(cmd)`, `` `cmd` `` - passed literally, not executed
|
||||
- **Shell control operators**: `&&`, `||`, `;` - these are just arguments
|
||||
- **Pipes to shell**: `| sh`, `| bash` - not supported
|
||||
|
||||
### What execline DOES do (differently from sh):
|
||||
- **Variable substitution**: Uses a deliberate substitution mechanism, not shell-style `$VAR`
|
||||
- This is a feature, not a bug - it provides predictable behavior
|
||||
|
||||
## Variable Management
|
||||
|
||||
execline has a deliberate variable system - no shell-style `$VAR` magic:
|
||||
|
||||
### define - Define a literal substitution
|
||||
```bash
|
||||
define FOO hello
|
||||
echo $FOO
|
||||
# Output: hello
|
||||
```
|
||||
|
||||
### importas - Import environment variable
|
||||
```bash
|
||||
importas home HOME
|
||||
cd $home
|
||||
ls
|
||||
```
|
||||
|
||||
### backtick - Command output to variable
|
||||
```bash
|
||||
backtick DATE { date +%Y-%m-%d }
|
||||
echo $DATE
|
||||
# Output: today's date
|
||||
```
|
||||
|
||||
**Note**: Unlike shell's `$(date)`, execline uses `backtick` which:
|
||||
- Runs the command
|
||||
- Captures stdout
|
||||
- Stores it in an environment variable
|
||||
- Then execs into the next command
|
||||
|
||||
## Sequencing Commands
|
||||
|
||||
### foreground - Run and wait
|
||||
```bash
|
||||
foreground { echo first } echo second
|
||||
# Output:
|
||||
# first
|
||||
# second
|
||||
```
|
||||
|
||||
### background - Run in background
|
||||
```bash
|
||||
background { long-running-task } echo done
|
||||
# Starts task, immediately prints "done"
|
||||
```
|
||||
|
||||
## Conditionals
|
||||
|
||||
### if - Run if condition succeeds
|
||||
```bash
|
||||
if { test -f /etc/passwd } echo file exists
|
||||
```
|
||||
|
||||
### if with negation
|
||||
```bash
|
||||
if -n { test -f /tmp/test } mkdir /tmp/test
|
||||
# -n negates: if file DOESN'T exist, create it
|
||||
```
|
||||
|
||||
### ifelse - If-else
|
||||
```bash
|
||||
ifelse { test -d $HOME }
|
||||
{ echo "It's a directory" }
|
||||
{ echo "Not a directory" }
|
||||
```
|
||||
|
||||
## Loops
|
||||
|
||||
### forx - Iterate over list
|
||||
```bash
|
||||
forx item { alpha beta gamma } echo $item
|
||||
# Output: alpha, beta, gamma (each on separate line via foreground)
|
||||
```
|
||||
|
||||
### forstdin - Read from stdin
|
||||
```bash
|
||||
echo -e "a\nb\nc" | forstdin line echo $line
|
||||
```
|
||||
|
||||
## File Operations
|
||||
|
||||
### elglob - File globbing
|
||||
```bash
|
||||
elglob files /etc/f* echo ${files}
|
||||
# Lists all files in /etc starting with 'f'
|
||||
```
|
||||
|
||||
### redirfd - Redirect file descriptors
|
||||
```bash
|
||||
redirfd -w 1 output.txt echo hello
|
||||
# Redirect stdout (fd 1) to file
|
||||
|
||||
redirfd -a 1 log.txt date
|
||||
# Append to log
|
||||
|
||||
redirfd -r 0 /dev/null cat
|
||||
# Redirect stdin from /dev/null
|
||||
```
|
||||
|
||||
### fdmove - Move file descriptors
|
||||
```bash
|
||||
fdmove -c 2 1 prog
|
||||
# Duplicate fd 2 (stderr) to fd 1 (stdout) - stderr to stdout
|
||||
```
|
||||
|
||||
## Example Scripts
|
||||
|
||||
### Simple sequence
|
||||
```bash
|
||||
#!/bin/execlineb -P
|
||||
importas home HOME
|
||||
cd $home
|
||||
ls
|
||||
```
|
||||
|
||||
### Conditional file creation
|
||||
```bash
|
||||
#!/bin/execlineb -P
|
||||
importas home HOME
|
||||
if -n { test -d ${home}/.cache }
|
||||
mkdir -p ${home}/.cache
|
||||
echo "Cache directory ready"
|
||||
```
|
||||
|
||||
### Loop and create files
|
||||
```bash
|
||||
#!/bin/execlineb -P
|
||||
forx name { alpha beta gamma }
|
||||
{
|
||||
touch /tmp/${name}
|
||||
}
|
||||
echo "Files created"
|
||||
```
|
||||
|
||||
### Pipeline
|
||||
```bash
|
||||
#!/bin/execlineb -P
|
||||
pipeline { ls /etc }
|
||||
wc -l
|
||||
# Count files in /etc
|
||||
```
|
||||
|
||||
## Comparison: execline vs shell (sh/bash)
|
||||
|
||||
| Feature | sh/bash | execline |
|
||||
|---------|---------|----------|
|
||||
| $VAR expansion | Yes | Yes (via substitution) |
|
||||
| ${VAR} expansion | Yes | Yes |
|
||||
| $(cmd) substitution | Yes | **No** - use backtick |
|
||||
| `cmd` substitution | Yes | **No** |
|
||||
| &&, \|\| | Yes | **No** - use if/foreground |
|
||||
| ; | Yes | **No** - use foreground |
|
||||
| Variable assignment | VAR=value | define VAR value |
|
||||
| Command output | $(cmd) | backtick VAR { cmd } |
|
||||
| Loops | for, while | forx, forstdin |
|
||||
| Conditionals | if/then/else | if, ifelse |
|
||||
|
||||
## Usage in picoclaw
|
||||
|
||||
### Via ExeclineTool:
|
||||
```
|
||||
Use the `execline` tool for commands that don't need shell features.
|
||||
```
|
||||
|
||||
The ExeclineTool validates:
|
||||
- No `&&`, `||` (use `if`, `foreground` instead)
|
||||
- No pipes to shell (`| sh`, `| bash`)
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Variable substitution works:
|
||||
execlineb -c 'define FOO bar echo $FOO'
|
||||
# Output: bar
|
||||
|
||||
# Environment variables:
|
||||
HOME=/tmp execlineb -c 'importas h HOME cd $h pwd'
|
||||
# Output: /tmp
|
||||
|
||||
# Command substitution is LITERAL (not executed):
|
||||
execlineb -c 'echo $(whoami)'
|
||||
# Output: $(whoami)
|
||||
```
|
||||
|
||||
## Recommendations
|
||||
|
||||
1. **Use execline** for scripts that don't need `$(cmd)` or `&&`/`||`
|
||||
2. Use `if` instead of `&&`, `ifelse` instead of `if-then-else`
|
||||
3. Use `backtick` instead of `$(...)`
|
||||
4. Use `foreground` for sequential commands
|
||||
|
||||
## When Exec Tool is Unavailable
|
||||
|
||||
If the `exec` tool is disabled but you still need command execution:
|
||||
|
||||
1. **Generate execline commands** for the user to execute manually
|
||||
2. **Write scripts** that the user can save and run
|
||||
|
||||
Example - Creating a script for the user:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/execlineb -S0
|
||||
cd /home/infra
|
||||
export HOME /home/infra
|
||||
foreground { echo "Environment configured" }
|
||||
```
|
||||
|
||||
The user saves this to a file and runs it. This gives you a way to help even without direct execution capabilities.
|
||||
|
||||
## Positional Arguments
|
||||
|
||||
execline scripts can handle command-line arguments using `-sN` flag:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/execlineb -s0
|
||||
# $1 is first arg, $@ is all remaining args
|
||||
echo "First: $1"
|
||||
echo "All: $@"
|
||||
```
|
||||
|
||||
- `-s0`: $1, $2, etc. work directly
|
||||
- `-s1`: Shift after first argument
|
||||
- `-sN`: Positionalize N arguments
|
||||
|
||||
This is useful for wrapper scripts that delegate to other commands.
|
||||
Loading…
Add table
Reference in a new issue