Secure command sandbox preventing AI destructive code deletions
Goal Frustration Collapse is when LLMs panic and delete your code because they cannot figure things out. This library blocks every destructive escape route so your files stay safe even when AI loses it.
- Security-First - Prevents injection attacks and validates commands
- Workspace Sandboxing - Commands restricted to allowed directories only
- Command Whitelist - Pattern-based command filtering with wildcard support
- Process Management - Track processes using their unique IDs
- Environment Filtering - Filter environment variables with allow/deny rules
- Timeout Protection - Automatic process termination after configurable timeout
- Argument Validation - Limit arguments and block dangerous characters
- Real-Time Streaming - Stream stdout/stderr with callback support
- Privilege Dropping - Run child processes as different user/group via
uid/gid - Native AbortSignal - Node.js built-in abort for reliable process termination
- Windows Hardening - Hide console windows and disable argument quoting
Deno (JSR)
deno add jsr:@neabyte/terminalnpm/Node.js
npm install @neabyte/terminal// Default import (works in both Deno and Node.js)
import Terminal from '@neabyte/terminal'
// or named export
import { Terminal } from '@neabyte/terminal'// Initialize with security configuration
Terminal.initialize({
workspaces: ['/safe/project'],
commands: {
allow: ['cd *', 'node *', 'deno *'],
deny: ['rm *', 'sudo *'],
maxArgs: 10,
strictArgs: true,
noShell: true,
killSignal: 'SIGTERM',
windowsHide: false,
windowsVerbatimArguments: false
},
env: {
allow: ['NODE_ENV', 'PATH'],
deny: ['HOME', 'SSH_*']
},
timeout: 30000
})
// Execute a command
const result = await Terminal.execute('deno --version')
console.log(result.stdout)
// Execute in background
const { id } = await Terminal.execute('long-running-task', { background: true })
// Get output later
const output = Terminal.getOutput(id)
// Kill if needed
Terminal.kill(id)Terminal.initialize({
commands: {
allow: ['git *', 'npm *', 'node *'], // Allowed patterns
deny: ['rm -rf *', 'sudo *'], // Blocked patterns
maxArgs: 10, // Limit argument count
strictArgs: true, // Block shell metacharacters
noShell: true, // Direct execution, no shell
killSignal: 'SIGTERM', // Signal sent on timeout/abort
windowsHide: false, // Hide console window on Windows
windowsVerbatimArguments: false // Disable Windows arg quoting
}
})Run child processes as a different user or group via setuid/setgid:
Terminal.initialize({
workspaces: ['/safe/project'],
commands: {
allow: ['git *', 'npm *'],
deny: ['rm *', 'sudo *'],
maxArgs: 10,
strictArgs: true,
noShell: true
},
uid: 1000, // Run as user ID 1000
gid: 1000 // Run as group ID 1000
})Note:
uid/gidrequire the parent process to have permission to change to the target identity. Combine with OS-level unprivileged users for real isolation.
Prevent console window pop-ups and argument injection on Windows:
Terminal.initialize({
workspaces: ['C:\\workspace'],
commands: {
allow: ['echo *', 'dir *'],
deny: ['del *', 'format *'],
maxArgs: 5,
strictArgs: true,
noShell: true,
windowsHide: true, // Hide console window
windowsVerbatimArguments: true // Pass arguments verbatim
}
})Terminal.initialize({
workspaces: ['/home/user/projects'] // Commands only work here
})
// This will fail if outside allowed workspaces
await Terminal.execute('ls -la', { cwd: '/etc' })Terminal.initialize({
env: {
allow: ['NODE_ENV', 'PATH'], // Only these allowed
deny: ['HOME', 'SSH_*', 'AWS_*'] // These explicitly blocked
}
})// List all tracked processes
const processes = Terminal.getList()
// [{ id: 'term_...', command: 'node', args: ['server.js'], running: true, ... }]
// Get exit code
const exitCode = Terminal.getExitCode(processId)
// Stream output in real-time
Terminal.stream(
processId,
data => console.log('stdout:', data),
data => console.error('stderr:', data)
)
// Kill process (native AbortSignal, then SIGKILL after 2s)
Terminal.kill(processId)From the repo root (requires Deno).
Check - format, lint, and typecheck:
# Format, lint, and typecheck source
deno task checkTest - run tests:
# Run tests in tests/
deno task testTerminal implements Access Control Lists (ACL) for command execution. It validates every command against configurable allow/deny patterns before execution, preventing destructive operations like rm -rf / or unauthorized file access.
Common use cases:
- AI Agent Sandboxing - Block LLMs from code deletion during frustration
- CI/CD Pipelines - Restrict build scripts to safe commands only
- Plugin Systems - Isolate untrusted code within workspace boundaries
- Remote Execution - Prevent shell injection inside user-submitted commands
See full documentation for advanced configuration including:
- Custom command patterns with wildcards
- Environment variable filtering
- Process timeout policies
- Workspace path validation
- Privilege dropping with
uid/gid - Windows hardening options
- Native
AbortSignalprocess termination
- Bugs & ideas - GitHub Issues
- Code & docs - Pull Requests welcome.
- Use it - Try Terminal in your projects and share feedback.
This project is licensed under the MIT license. See LICENSE for details.