---
title: "Security Best Practices"
source: https://docs.autohand.ai/guides/security-best-practices
---

# Security Best Practices

Autohand operates on your code with real file system access and command execution. This guide covers how to configure permissions, protect sensitive files, sandbox commands, and set up team-wide security policies.

**Related Skills:** Enhance your security posture with specialized skills from [Skilled](https://skilled.autohand.ai). Browse [security scanning skills](https://skilled.autohand.ai/categories/quality), [security audit workflows](https://skilled.autohand.ai/categories/workflows), and [compliance skills](https://skilled.autohand.ai/categories/devops) to protect your codebase.

## Permission modes

Autohand has three permission modes that control how much freedom the agent has when interacting with your system. Choosing the right mode depends on the task and how much you trust the environment.

### Interactive mode (default)

The agent asks for your approval before performing any potentially dangerous action. This is the safest mode for daily work. Every file write, command execution, and deletion prompts you with a yes/no confirmation.

``` bash
# Default behavior, no flag needed
autohand "Refactor the auth module"

# The agent will prompt before each action:
# Allow writing to src/auth/middleware.ts? [y/n]
# Allow running: npm test? [y/n]
```

Use interactive mode when you are exploring a codebase for the first time, working on sensitive parts of your system, or running Autohand on a project you are not familiar with.

### Unrestricted mode

The agent performs all actions without asking for permission. This is useful for trusted, well-scoped tasks where you have already reviewed the plan.

``` bash
# Allow all actions without prompts
autohand --unrestricted "Add unit tests for every file in src/utils/"
```

Caution

Unrestricted mode gives the agent full access to read, write, and execute within your workspace. Only use it on isolated branches or when you can easily revert changes.

### Restricted mode

The agent can only read files and search the codebase. It cannot write files, run commands, or make any modifications. This is the right choice for code review and analysis tasks.

``` bash
# Read-only mode for safe analysis
autohand --restricted "Review the payment flow for security vulnerabilities"

# Also useful in CI where you don't want any side effects
git diff main...HEAD | autohand --headless --restricted \
  --prompt "Review this diff for bugs"
```

### Comparing the modes

| Capability | Interactive | Unrestricted | Restricted |
|---|---|---|---|
| Read files | Yes | Yes | Yes |
| Write files | With approval | Yes | No |
| Run commands | With approval | Yes | No |
| Delete files | With approval | Yes | No |
| Best for | Daily development | Trusted automation | Code review, CI |

## Fine-grained permissions

Beyond the three main modes, you can define exactly which tools and commands the agent is allowed to use. Permission patterns let you whitelist safe operations and block dangerous ones.

### Whitelist patterns

Allow specific commands while keeping everything else under interactive approval:

``` bash
# Allow npm and node commands without prompts
autohand --allow "run_command:npm *" --allow "run_command:node *" \
  "Fix all lint errors and run the tests"
```

### Blacklist patterns

Block specific dangerous operations while allowing everything else:

``` bash
# Block all deletion commands
autohand --deny "run_command:rm *" --deny "delete_path:*" \
  "Clean up the unused modules in src/legacy/"
```

### Pattern matching syntax

Permission patterns follow the format `tool_name:argument_pattern`. The `*` wildcard matches any string. You can combine multiple `--allow` and `--deny` flags in one command.

``` bash
# Allow writing to src/ but block writes to config files
autohand --allow "write_file:src/*" --deny "write_file:*.config.*" \
  "Refactor the service layer"

# Allow git commands but block force push
autohand --allow "run_command:git *" --deny "run_command:git push --force*" \
  "Create a commit with the staged changes"
```

### Permission patterns in configuration

Instead of passing flags every time, set default permissions in your project configuration file:

``` json
// .autohand/config.json
{
  "permissions": {
    "allow": [
      "run_command:npm *",
      "run_command:node *",
      "run_command:git add *",
      "run_command:git commit *",
      "write_file:src/*",
      "write_file:tests/*"
    ],
    "deny": [
      "run_command:rm -rf *",
      "run_command:git push --force*",
      "write_file:.env*",
      "write_file:*.pem",
      "delete_path:/"
    ]
  }
}
```

The config file applies to everyone on the team, so it is a good place to encode your project's safety rules.

## YOLO mode safety

YOLO mode (also called `--yes` or `--unrestricted`) lets the agent run without prompts. Used carelessly, it can overwrite files or run destructive commands. The key to using it safely is pairing it with deny patterns that act as guardrails.

### Safe YOLO with deny patterns

Allow everything except the operations you never want to happen:

``` bash
# YOLO mode with safety rails
autohand --unrestricted \
  --deny "delete_path:*" \
  --deny "run_command:rm *" \
  --deny "run_command:git push *" \
  --deny "write_file:.env*" \
  "Add error handling to all API routes"
```

### Scoped YOLO for testing

When generating tests, you usually want the agent to create files freely. Limit the scope so it only writes to the test directory:

``` bash
# Free reign in tests, locked everywhere else
autohand --unrestricted \
  --allow "write_file:tests/*" \
  --allow "write_file:src/**/__tests__/*" \
  --deny "write_file:src/**/*.ts" \
  --deny "delete_path:*" \
  "Generate comprehensive tests for the billing module"
```

### YOLO in CI with safety nets

In CI environments, combine YOLO mode with restricted scope and dry-run checks:

``` bash
# CI: auto-fix lint errors, but verify with dry-run first
autohand --headless --unrestricted --dry-run \
  --prompt "Fix all ESLint errors in src/"

# If dry-run looks good, apply for real
autohand --headless --unrestricted \
  --deny "delete_path:*" \
  --deny "run_command:git push *" \
  --prompt "Fix all ESLint errors in src/"
```

**Tip:** Always run `--dry-run` first to preview what YOLO mode will do. This lets you verify the scope of changes before they happen.

## Workspace safety

Autohand automatically prevents the agent from operating on directories it should never touch. These built-in protections stop accidental damage to your system.

### Protected directories

The agent will refuse to write or execute commands in these locations, regardless of permissions:

-   `/` (root directory)
-   `~` (home directory, unless your project lives there)
-   `/etc`, `/usr`, `/bin`, `/sbin` (system directories)
-   `/System`, `/Library` (macOS system directories)
-   `C:\Windows`, `C:\Program Files` (Windows system directories)

If you try to point Autohand at your home directory, it will ask you to narrow the scope:

``` bash
# This will be rejected
autohand --add-dir ~ "Clean up old projects"
# Error: Cannot operate on home directory. Please specify a project subdirectory.

# This is fine
autohand --add-dir ~/projects/my-app "Clean up unused modules"
```

### Scope limiting with --add-dir

By default, Autohand operates in the current working directory. You can expand its scope with `--add-dir`, but only to specific directories you trust:

``` bash
# Work across two related projects
autohand --add-dir ../shared-lib "Update the shared library types to match the API changes in this project"

# Add a data directory for analysis
autohand --add-dir ./data --restricted "Analyze the CSV files in the data directory and suggest schema improvements"
```

### Git worktree isolation

For risky operations, use a git worktree so that changes happen on a separate branch in an isolated directory:

``` bash
# Create an isolated worktree for the refactoring
git worktree add ../refactoring-branch -b refactoring
cd ../refactoring-branch
autohand --unrestricted "Refactor the entire API layer to use the new router"

# Review changes, then merge if they look good
git diff main
cd ../main-project
git merge refactoring
```

## Hook-based guardrails

Hooks let you run custom logic before or after the agent takes an action. You can use them to enforce policies, log activity, and block specific operations based on your own rules.

### Block writes to production configs

Prevent the agent from modifying production configuration files:

``` json
// .autohand/hooks.json
{
  "pre_write_file": [
    {
      "match": "config/production.*",
      "action": "deny",
      "message": "Cannot modify production config files. Make changes in config/development.* and promote through your deployment pipeline."
    },
    {
      "match": "docker-compose.prod.yml",
      "action": "deny",
      "message": "Production Docker Compose file is managed by infrastructure team."
    }
  ]
}
```

### Require approval for database commands

Add an extra confirmation step before any database-related commands:

``` json
// .autohand/hooks.json
{
  "pre_run_command": [
    {
      "match": "*migrate*",
      "action": "confirm",
      "message": "This command appears to run a database migration. Are you sure?"
    },
    {
      "match": "*seed*",
      "action": "confirm",
      "message": "This command will seed the database. Confirm before proceeding."
    },
    {
      "match": "psql*",
      "action": "deny",
      "message": "Direct database access is not allowed through the agent."
    }
  ]
}
```

### Log all file modifications

Keep an audit trail of every file the agent modifies:

``` json
// .autohand/hooks.json
{
  "post_write_file": [
    {
      "match": "*",
      "action": "run",
      "command": "echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) WRITE ${AUTOHAND_FILE_PATH}\" >> .autohand/audit.log"
    }
  ],
  "post_run_command": [
    {
      "match": "*",
      "action": "run",
      "command": "echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) EXEC ${AUTOHAND_COMMAND}\" >> .autohand/audit.log"
    }
  ]
}
```

### Enforce code style on writes

Automatically format files after the agent writes them:

``` json
// .autohand/hooks.json
{
  "post_write_file": [
    {
      "match": "*.ts",
      "action": "run",
      "command": "npx prettier --write ${AUTOHAND_FILE_PATH}"
    },
    {
      "match": "*.py",
      "action": "run",
      "command": "black ${AUTOHAND_FILE_PATH}"
    }
  ]
}
```

## Sensitive file protection

Certain files should never be read or modified by the agent. Environment files, API keys, certificates, and credentials need explicit protection.

### Default protected patterns

Autohand automatically avoids reading or writing these file patterns:

-   `.env`, `.env.*` - Environment variable files
-   `*.pem`, `*.key`, `*.cert` - Certificates and keys
-   `id_rsa`, `id_ed25519` - SSH keys
-   `credentials.json`, `serviceAccountKey.json` - Cloud credentials

If the agent tries to read a protected file, it will receive an empty result with a note that the file is protected.

### Custom protection patterns

Add your own patterns to the deny list in the configuration:

``` json
// .autohand/config.json
{
  "permissions": {
    "deny": [
      "read_file:.env*",
      "read_file:*.secret",
      "read_file:config/secrets/*",
      "read_file:**/credentials*",
      "write_file:.env*",
      "write_file:*.pem",
      "write_file:*.key",
      "write_file:config/production.*"
    ]
  }
}
```

### Using .autohandignore

Create an `.autohandignore` file (similar to `.gitignore`) to exclude files from the agent's view entirely:

``` bash
# .autohandignore
.env
.env.*
*.pem
*.key
*.cert
config/secrets/
credentials/
**/serviceAccountKey.json
**/*.secret.yaml
node_modules/
.git/
```

Files listed in `.autohandignore` will not appear in search results, will not be read by the agent, and will not be offered as context. This is the strongest form of protection because the agent does not even know these files exist.

### Verifying protection

Test that your protections work by asking the agent to read a protected file:

``` bash
# Verify sensitive files are protected
autohand --restricted "Can you read the contents of .env?"
# Expected: The agent reports that the file is protected or not accessible
```

## Sandbox mode

Sandbox mode isolates command execution so that the agent's shell commands cannot affect your host system beyond the project directory. This adds an extra layer of defense on top of permission controls.

### Enabling sandbox mode

``` bash
# Run with sandboxed command execution
autohand --sandbox "Install the testing dependencies and run the full test suite"
```

### What sandbox mode does

When sandbox mode is active:

-   Commands can only access files within the project directory
-   Network access follows your configured rules (default: allowed for package managers)
-   No commands can modify files outside the project root
-   Environment variables are filtered to remove sensitive values
-   Process spawning is limited to the allowed command list

### Sandbox configuration

Fine-tune sandbox behavior in your project configuration:

``` json
// .autohand/config.json
{
  "sandbox": {
    "enabled": true,
    "network": {
      "allow": ["registry.npmjs.org", "pypi.org", "crates.io"],
      "deny": ["*"]
    },
    "env_filter": [
      "AUTOHAND_API_KEY",
      "AWS_*",
      "DATABASE_URL",
      "GITHUB_TOKEN"
    ],
    "allowed_commands": [
      "npm", "npx", "node", "bun",
      "python", "pip", "pytest",
      "cargo", "rustc",
      "git", "make"
    ]
  }
}
```

### Sandbox in CI

Sandbox mode is especially valuable in CI where the agent runs unattended:

``` yaml
# GitHub Actions with sandboxed Autohand
- name: Autohand Fix
  run: |
    autohand --headless --sandbox --unrestricted \
      --prompt "Fix the failing tests in src/api/"
```

## Local model privacy

If your code must stay on your machine, you can run Autohand with a local model. No data leaves your network when you use a local backend. This is the right choice for classified projects, healthcare code, financial systems, or any codebase with strict data residency rules.

### Using Ollama

Run a model locally with Ollama and point Autohand at it:

``` bash
# Pull and start a model
ollama pull deepseek-coder:33b

# Point Autohand to the local model
AUTOHAND_PROVIDER=ollama \
AUTOHAND_MODEL=deepseek-coder:33b \
autohand "Refactor the authentication middleware"
```

### Using llama.cpp

For maximum control over the inference stack:

``` bash
# Start llama.cpp server
./llama-server -m models/codellama-34b.Q5_K_M.gguf --port 8080

# Connect Autohand
AUTOHAND_PROVIDER=openai-compatible \
AUTOHAND_API_BASE=http://localhost:8080/v1 \
AUTOHAND_MODEL=codellama-34b \
autohand "Add input validation to the user registration endpoint"
```

### Using MLX on Apple Silicon

Take advantage of Apple's Metal framework for fast local inference on M-series Macs:

``` bash
# Install MLX server
pip install mlx-lm

# Start the server
mlx_lm.server --model mlx-community/deepseek-coder-33b-4bit --port 8080

# Connect Autohand
AUTOHAND_PROVIDER=openai-compatible \
AUTOHAND_API_BASE=http://localhost:8080/v1 \
autohand "Write tests for the payment processing module"
```

### Verifying no data leaves your machine

You can confirm that all traffic stays local by monitoring network connections:

``` bash
# Monitor outbound connections while running Autohand
sudo lsof -i -n | grep autohand

# Or use a stricter approach: block all outbound traffic for the process
# On macOS, use Little Snitch or the built-in firewall
# On Linux, use iptables rules scoped to the user
```

## Team security

When multiple developers use Autohand on the same project, you need consistent policies. Configuration files checked into the repository ensure that everyone operates under the same security rules.

### Shared permission policies

Commit your security configuration to the repository so every team member inherits it:

``` json
// .autohand/config.json (committed to repo)
{
  "permissions": {
    "allow": [
      "run_command:npm *",
      "run_command:bun *",
      "run_command:git add *",
      "run_command:git commit *",
      "write_file:src/*",
      "write_file:tests/*"
    ],
    "deny": [
      "run_command:rm -rf *",
      "run_command:git push --force*",
      "run_command:git rebase*",
      "write_file:.env*",
      "write_file:*.pem",
      "write_file:*.key",
      "write_file:config/production.*",
      "write_file:infrastructure/*",
      "delete_path:*"
    ]
  }
}
```

### Protecting company secrets

Use a combination of `.autohandignore` and deny patterns to keep secrets out of the agent's reach:

``` bash
# .autohandignore (committed to repo)
# Secrets and credentials
.env
.env.*
config/secrets/
*.pem
*.key

# Internal documentation
docs/internal/
docs/architecture/threat-model.md

# Infrastructure
terraform/*.tfvars
ansible/vault/
```

### Audit logging with hooks

Set up hooks to log every action the agent takes, creating an audit trail for compliance:

``` json
// .autohand/hooks.json (committed to repo)
{
  "post_write_file": [
    {
      "match": "*",
      "action": "run",
      "command": "echo '{\"timestamp\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"action\":\"write\",\"file\":\"'${AUTOHAND_FILE_PATH}'\",\"user\":\"'$(whoami)'\"}' >> .autohand/audit.jsonl"
    }
  ],
  "post_run_command": [
    {
      "match": "*",
      "action": "run",
      "command": "echo '{\"timestamp\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"action\":\"exec\",\"command\":\"'${AUTOHAND_COMMAND}'\",\"user\":\"'$(whoami)'\"}' >> .autohand/audit.jsonl"
    }
  ]
}
```

The audit log records who ran the agent, what it did, and when. Add `.autohand/audit.jsonl` to your `.gitignore` but ship it to your central logging system for compliance teams.

### Role-based permissions

For larger teams, use environment-specific config files that give different access levels to different roles:

``` bash
# Developers: standard permissions
AUTOHAND_CONFIG=.autohand/config.dev.json autohand "Fix the failing tests"

# Senior engineers: expanded permissions
AUTOHAND_CONFIG=.autohand/config.senior.json autohand "Refactor the database layer"

# CI bot: restricted to read-only analysis
AUTOHAND_CONFIG=.autohand/config.ci.json autohand --headless --restricted \
  --prompt "Review the latest changes"
```

## Security checklist

Use this checklist when setting up Autohand for a new project or team. Each item takes a few minutes and significantly reduces risk.

![Autohand permission system prompting for approval before file operations](/demos/autohand-permissions.gif)

### Initial setup

-   Create `.autohand/config.json` with deny patterns for dangerous operations
-   Create `.autohandignore` to exclude secrets, keys, and internal docs
-   Commit both files to the repository
-   Store API keys in environment variables, never in config files

### Daily usage

-   Use interactive mode (the default) for most work
-   Use `--restricted` for code review and analysis
-   Use `--dry-run` before running `--unrestricted`
-   Review the agent's plan before confirming batch operations

### CI/CD pipelines

-   Always use `--headless` in CI environments
-   Default to `--restricted` for review and analysis jobs
-   Use `--sandbox` when the agent needs write access in CI
-   Store `AUTOHAND_API_KEY` as a CI secret, not in the workflow file
-   Set timeouts on all Autohand steps to prevent hanging jobs

### Team rollout

-   Document your team's Autohand security policy
-   Set up audit logging with hooks
-   Ship audit logs to your central logging platform
-   Review and update deny patterns quarterly
-   Test your protections by trying to access blocked resources

### Enterprise environments

-   Evaluate local model deployment for air-gapped or regulated environments
-   Configure network-level controls for cloud API access
-   Set up role-based permission configs for different team tiers
-   Integrate audit logs with your SIEM or compliance platform
-   Include Autohand configuration in your security review process

## Next steps

-   [CI/CD Automation](/docs/guides/ci-cd-automation.html) - Set up Autohand in your build pipelines
-   [Hooks Reference](/docs/working-with-autohand-code/hooks.html) - Full documentation on hook configuration
-   [YOLO Mode](/docs/working-with-autohand-code/yolo-mode.html) - Detailed reference for unrestricted operation
-   [Configuration](/docs/working-with-autohand-code/configuration.html) - All configuration options explained
-   [Enterprise Security](/docs/guides/enterprise-security.html) - Advanced deployment and compliance