Guide for running language interpreters through Terminal's command filter.
Critical: Terminal validates the command string, not what the command does. Any allowed interpreter can execute arbitrary code via script files.
With strictArgs: true (default), shell metacharacters including parentheses () are blocked. This affects inline code execution:
// BLOCKED - Parentheses detected as shell metacharacters
await Terminal.execute('python3 -c print(42)')
await Terminal.execute('deno eval console.log(42)')
await Terminal.execute('node -e console.log(42)')Error: Argument validation failed: Invalid characters in argument 1: shell metacharacters detected
For trusted environments only:
Terminal.initialize({
workspaces: ['/safe/project'],
commands: {
allow: ['deno', 'python3', 'node'],
deny: ['sudo'],
maxArgs: 20,
strictArgs: false, // Allow () for function calls
noShell: true
}
})
// Now works
await Terminal.execute('python3 -c print(42)')Warning
Security Risk: Disables protection against shell injection. Only use in controlled environments.
Write code to file first, then execute:
const scriptPath = '/safe/project/script.py'
await Deno.writeTextFile(scriptPath, `print("hello")`)
const result = await Terminal.execute(`python3 ${scriptPath}`)Caution
Terminal does NOT inspect file contents. A script file can contain os.system('rm -rf /') and Terminal will pass it through. File-based execution requires OS-level hardening:
- Run as unprivileged user
- Use filesystem permissions (
chmod 600) - Consider chroot or containers
- Pre-approve script files, do not let AI write them
For common operations, prepare and audit scripts in advance. Do not let AI agents write script files dynamically.
// Script is pre-audited and immutable
const result = await Terminal.execute('python3 /safe/project/scripts/check-version.py')Terminal's parser splits commands on whitespace only:
| Input | Parsed As | Note |
|---|---|---|
echo a b c |
['echo', 'a', 'b', 'c'] |
✅ Works |
echo a,b,c |
['echo', 'a,b,c'] |
✅ Comma stays in arg |
cmd; rm / |
['cmd;', 'rm', '/'] |
❌ ; is part of arg 0 |
a && b |
['a', '&&', 'b'] |
❌ && becomes arg 1 |
Shell operators do NOT work (even with strictArgs: false):
// Parsed as separate args, NOT chained commands
await Terminal.execute('deno eval console.log(1), console.log(2)')
// Args: ['deno', 'eval', 'console.log(1),', 'console.log(2)']import Terminal from '@neabyte/terminal'
Terminal.initialize({
workspaces: ['/workspace'],
commands: {
allow: ['python3 /workspace/preinstalled/*.py'],
deny: ['sudo'],
maxArgs: 5,
strictArgs: true,
noShell: true
},
timeout: 10000
})
// Only execute pre-audited scripts
const result = await Terminal.execute('python3 /workspace/preinstalled/hello.py arg1 arg2')
console.log(result.stdout)- Never allow
node,python3,denowith wildcard patterns -node /workspace/*.jsis a sandbox bypass - Always use
noShell: true- Prevents shell interpretation - Pre-install scripts, never generate them at runtime - Terminal does not inspect file contents
- Combine with OS hardening - See Security for chroot, containers, seccomp
- Run as unprivileged user - Never run Terminal as root
- Security - OS-level hardening guide
- Configuration - Security settings reference
- Common Errors - Troubleshooting guide