Skip to content

Security: DenysVuika/squid

Security

docs/SECURITY.md

Security Features

This document describes the security features implemented in squid to protect users during LLM interactions with tool calling capabilities, including path validation and ignore patterns.

Quick Start: See the "Tool Calling (with Security Approval)" section in the main README.md for examples.

Overview

When the LLM requests to use tools (such as reading, writing, or searching files), squid provides multiple layers of security:

  1. Path Validation - Whitelist/blacklist rules prevent access to sensitive system directories
  2. Ignore Patterns - .squidignore file blocks access to specific files and directories
  3. User Approval - Explicit confirmation required before executing any operation

This multi-layered approach prevents unauthorized or unintended file system access.

Tool Approval Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. User sends a query to the LLM                            β”‚
β”‚    Example: "Read README.md and summarize it"               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. LLM determines it needs to use a tool                    β”‚
β”‚    Tool: read_file                                          β”‚
β”‚    Arguments: {"path": "README.md"}                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. squid validates path (whitelist/blacklist + .squidignore)β”‚
β”‚    β†’ If blocked: Friendly message returned to LLM           β”‚
β”‚                  (NO user prompt, LLM relays message)       β”‚
β”‚    β†’ If allowed: Continue to step 4                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. squid prompts user for approval                          β”‚
β”‚                                                             β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚    β”‚ Allow reading file: README.md? (Y/n)              β”‚    β”‚
β”‚    β”‚ [Y] Allow  [N] Skip                               β”‚    β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 5. User makes decision                                      β”‚
β”‚    β€’ Press Y β†’ Tool executes, result sent to LLM            β”‚
β”‚    β€’ Press N β†’ Tool skipped, error sent to LLM              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Note: The LLM will still make tool call requests for protected files because it doesn't know which files are blocked beforehand. However, these requests are rejected instantly without user interaction, and the LLM receives a friendly message to relay to the user.

Security Features

πŸ›‘οΈ Path Validation (Whitelist/Blacklist)

All file system operations are validated against whitelist and blacklist rules before requesting user approval.

Default Whitelist:

  • Current directory (.) and subdirectories
  • Current working directory path

Default Blacklist (System Paths):

  • /etc, /bin, /sbin, /usr/bin, /usr/sbin
  • /root, /var, /sys, /proc
  • C:\Windows, C:\Program Files (Windows)

Default Blacklist (Sensitive User Files):

  • ~/.ssh/ - SSH keys
  • ~/.gnupg/ - GPG keys
  • ~/.aws/ - AWS credentials
  • ~/.config/gcloud/ - Google Cloud credentials

Behavior:

  • Paths outside the whitelist are automatically rejected
  • Paths in the blacklist are automatically rejected
  • User is never prompted for rejected paths
  • Clear error messages explain why access was denied

Example:

squid ask "Read /etc/passwd"

# What happens:
# 1. LLM requests to read /etc/passwd
# 2. Path validation blocks it (blacklisted)
# 3. Friendly message returned to LLM (no user prompt)
# 4. LLM relays the message:
#
# πŸ¦‘: I cannot access '/etc/passwd' because it's a protected system file 
# or directory. Access to this location is blocked for security reasons.

πŸ“‚ Ignore Patterns (.squidignore)

Use a .squidignore file in your project root to specify files and directories that should never be accessed by squid tools. This works like .gitignore.

Creating .squidignore:

# .squidignore - One pattern per line
# Lines starting with # are comments

# Build outputs
target/
dist/
*.o

# Dependencies  
node_modules/
__pycache__/

# Secrets
.env
*.key
*.pem

# Logs
*.log
logs/

# OS files
.DS_Store

Pattern Syntax:

  • *.txt - All .txt files in any directory
  • **/*.log - All .log files recursively
  • target/ - Entire target directory
  • node_modules/** - node_modules and all contents
  • # comment - Comments start with #

Priority:

Ignore patterns are checked after whitelist/blacklist but before user approval:

1. Path validation (whitelist/blacklist) ← Automatic
2. Ignore patterns (.squidignore)        ← Automatic  
3. User approval prompt                  ← Manual

Example:

# Create .squidignore
echo "*.log" > .squidignore
echo ".env" >> .squidignore

squid ask "Read debug.log"

# What happens:
# 1. LLM requests to read debug.log
# 2. Path validation blocks it (.squidignore pattern match)
# 3. Friendly message returned to LLM (no user prompt)
# 4. LLM relays the message:
#
# πŸ¦‘: I cannot access 'debug.log' because it's protected by the project's 
# .squidignore file. This is a security measure to prevent access to 
# sensitive files.

πŸ”’ User Approval Required

All tool executions require explicit user approval. The LLM cannot read, write, or search files without user consent.

squid ask "Read my secret.txt file"
# Prompt: Allow reading file: secret.txt? (Y/n)
# β†’ You control whether this happens

squid ask "Search for passwords in the project"
# Prompt: Allow searching for pattern 'passwords' in: .? (Y/n)
# β†’ You control whether this happens

πŸŽ›οΈ Tool Permissions (Per-Agent)

Squid uses agent-based permissions where each agent defines which tools can run automatically (without confirmation) or should never run at all.

Configuration:

{
  "agents": {
    "general-assistant": {
      "name": "General Assistant",
      "enabled": true,
      "description": "Full-featured coding assistant",
      "model": "qwen2.5-coder",
      "permissions": {
        "allow": ["now", "read_file", "write_file", "grep", "bash:ls", "bash:git"],
        "deny": []
      }
    },
    "code-reviewer": {
      "name": "Code Reviewer",
      "enabled": true,
      "description": "Reviews code (read-only)",
      "model": "qwen2.5-coder",
      "permissions": {
        "allow": ["now", "read_file", "grep"],
        "deny": ["write_file", "bash"]
      }
    }
  },
  "default_agent": "general-assistant"
}

Fields:

  • allow - Tools that run automatically without user confirmation
  • deny - Tools that are completely blocked and will never run

Default Behavior:

  • Each agent defines its own permission set
  • CLI commands use the default_agent permissions
  • Web UI uses the selected agent's permissions
  • All other tools require confirmation on first use

Interactive Permission Management:

When prompted for tool approval, you have four options:

Can I read this file?
  πŸ“„ File: config.json

❯ Yes (this time)
  No (skip)
  Always (add to allow list)
  Never (add to deny list)

Options:

  • Yes (this time) - Allow once, ask again next time
  • No (skip) - Deny once, ask again next time
  • Always (add to allow list) - Allow this tool permanently for the current agent, auto-save to config
  • Never (add to deny list) - Block this tool permanently for the current agent, auto-save to config

Permission Priority:

  1. Deny list (highest priority) - Tool is blocked immediately
  2. Allow list - Tool runs without confirmation
  3. Default - User is prompted for approval

Security Notes:

  • Permissions are stored per-agent in squid.config.json
  • Different agents can have different permission levels
  • Path validation still applies to allowed tools (whitelist/blacklist/.squidignore)
  • Denied tools return an error to the LLM without user interaction

🎯 Granular Bash Permissions

Each agent's bash permissions support granular control for fine-grained management of which commands can run without approval:

Format:

  • "bash" - Allows all bash commands (uses internal safety checks)
  • "bash:ls" - Allows only ls commands (ls, ls -la, ls -l, etc.)
  • "bash:git" - Allows only git commands (any git subcommand)
  • "bash:git status" - Allows only git status commands specifically
  • "bash:cat" - Allows only cat commands

Example Agent Configuration with Granular Bash Permissions:

{
  "agents": {
    "safe-explorer": {
      "name": "Safe Explorer",
      "enabled": true,
      "description": "Read-only agent with safe bash commands",
      "model": "qwen2.5-coder",
      "permissions": {
        "allow": [
          "now",
          "read_file", 
          "grep",
          "bash:ls",
          "bash:git status",
          "bash:pwd"
        ],
        "deny": [
          "write_file",
          "bash:rm",
          "bash:sudo"
        ]
      }
    }
  }
}

This agent configuration:

  • βœ… Auto-approves ls commands without prompting
  • βœ… Auto-approves git status (but not other git commands)
  • βœ… Auto-approves pwd command
  • ❌ Blocks all rm commands (in addition to built-in blocking)
  • ❌ Blocks all sudo commands (in addition to built-in blocking)
  • ❓ Prompts for other bash commands (like cat, echo, git log)

How Granular Permissions Work:

When you choose Always or Never for a bash command, the system automatically extracts the base command and saves it:

# User approves: "ls -la" with "Always"
# Saved as: "bash:ls"
# Now allows: ls, ls -la, ls -l, etc.

# User approves: "git status" with "Always"  
# Saved as: "bash:git status"
# Now allows: git status, git status --short
# Still prompts for: git log, git commit, etc.

# User denies: "rm -rf temp" with "Never"
# Saved as: "bash:rm"
# Now blocks: rm, rm -rf, rm -f, etc.

Benefits:

  • 🎯 Precision: Allow only specific safe commands
  • πŸ”’ Safety: Deny dangerous commands beyond built-in blocks
  • ⚑ Efficiency: Reduce prompts for frequently used safe commands
  • πŸ“ Clarity: Config clearly shows which commands are trusted

Critical Security Note: Dangerous command patterns (rm, sudo, chmod, dd, curl, wget, kill) are always blocked at the code level and cannot be bypassed by:

  • Adding "bash" to allow list
  • Adding "bash:rm" to allow list
  • User approval
  • Any configuration setting

These blocks are hardcoded for your safety and cannot be overridden.

πŸ“‹ Content Preview for Write Operations

When the LLM attempts to write a file, you see a preview of the content before approving:

squid ask "Create a config.json file with default settings"

# You'll see:
# Allow writing to file: config.json?
# Content preview:
# {
#   "version": "1.0",
#   "debug": false,
#   "port": 8080
# }
# (Y/n)

For large content (>100 bytes), only the first 100 bytes are shown with a total size indicator.

πŸ” Search Pattern Transparency

When the LLM attempts to search files using grep, you see the exact pattern and path:

squid ask "Find all TODO comments in src"

# You'll see:
# Allow searching for pattern 'TODO' in: src? (Y/n)

Search features:

  • Regex pattern matching with case sensitivity options
  • Recursive directory search or single file search
  • Results show file path, line number, and matched content
  • Automatic binary file filtering for safety
  • Configurable result limits (default: 50 matches)

πŸ“ Comprehensive Logging

All tool calls are logged for transparency and audit purposes:

[INFO] Tool call: read_file with args: {"path":"README.md"}
[INFO] Successfully read file: README.md (2847 bytes)

Or if denied:

[INFO] Tool call: write_file with args: {"path":"secret.txt","content":"..."}
[INFO] Tool execution skipped by user: write_file

🚫 Denial of Service Protection

Users can deny any tool execution at any time:

  • Press N to skip the operation
  • The LLM receives an error message
  • The LLM can adapt its response based on the denial
  • No files are accessed or modified

Supported Tools

read_file

Purpose: Read contents from the file system

Security measures:

  • Shows exact file path before approval
  • No preview of file contents (you approve based on the path)
  • Logged with file size after successful read

Example prompt:

Allow reading file: /path/to/file.txt? (Y/n)

write_file

Purpose: Write content to the file system

Security measures:

  • Shows exact file path before approval
  • Displays content preview (first 100 bytes)
  • Shows total byte count for large files
  • Logged with file size after successful write

Example prompt:

Allow writing to file: output.txt?
Content preview:
Hello, World!
This is a test file.
(Y/n)

now

Purpose: Get current date and time in RFC 3339 format

Security measures:

  • Shows which timezone will be used (UTC or local)
  • No sensitive data access - only system time
  • Logged with timezone information

Example prompt:

Allow getting current date and time?
Timezone: utc
(Y/n)

bash

Purpose: Execute safe, non-destructive bash commands for system inspection

Security measures:

  • MANDATORY blocking of dangerous commands - Cannot be bypassed by configuration or user approval
  • Blocked patterns (hardcoded): rm -rf, rm -f, sudo, chmod, dd, mkfs, fdisk, curl, wget, kill, pkill, killall
  • Dangerous commands are blocked before permission checks and user prompts
  • Shows exact command and timeout before approval (for non-dangerous commands)
  • Configurable timeout (default: 10 seconds, max: 60 seconds)
  • Command execution wrapped in timeout protection
  • Logged with command and execution status

Allowed use cases:

  • Information gathering: ls, ls -la, pwd
  • Git inspection: git status, git log, git branch
  • File viewing: cat file.txt, head, tail
  • System info: echo, date, uname
  • Search operations: find, command-line grep

Example prompt:

Allow executing bash command?
Command: ls -la
Timeout: 10 seconds
(Y/n)

Security notes:

  • Commands are executed in a shell subprocess with timeout protection
  • Dangerous commands are blocked before user approval is requested
  • Even if a command is in the allow list, dangerous patterns are still blocked
  • Path validation does not apply (bash operates on the shell level)
  • Users should review commands carefully before approval

Example of blocked command:

squid ask "Delete all temporary files with rm -rf /tmp/*"

# What happens:
# 1. LLM requests to execute: rm -rf /tmp/*
# 2. MANDATORY security check detects "rm -rf" pattern (happens BEFORE permissions)
# 3. Command is blocked immediately (no permission check, no user prompt)
# 4. Error returned to LLM:
#
# πŸ¦‘: Command blocked for security reasons. The command contains a 
# dangerous pattern: 'rm -rf'. Commands like rm, sudo, chmod, dd, curl, 
# wget, and kill operations are not allowed.

Even with "bash" in agent allow list:

{
  "agents": {
    "general-assistant": {
      "permissions": {
        "allow": ["bash"]  // Allow all bash? NO - dangerous commands still blocked!
      }
    }
  }
}
squid ask "Run: rm -rf temp"
# Still blocked! Dangerous patterns cannot be bypassed by configuration.

Direct File Access Commands

In addition to LLM tool calls, squid provides direct file access via command-line flags:

  • ask -f <file> - Passes file content directly to the LLM with your question
  • review <file> - Reads file for code review

Security measures:

  • Path validation applied BEFORE reading - Same whitelist/blacklist and .squidignore checks as tool calls
  • No user approval prompt - Validation happens immediately when command runs
  • Friendly error messages - Clear explanation if file is blocked
  • Cannot bypass security - No way to override validation rules

Example blocked access:

$ squid ask -f .env "what's in this file?"
πŸ¦‘: I can't access that file - it's in your .squidignore list.

$ squid review ~/.ssh/id_rsa
πŸ¦‘: I can't access that file - it's outside the project directory or in a protected system location.

Example allowed access:

$ squid ask -f src/main.rs "explain this code"
# File is validated, then read and passed to LLM
# No approval prompt needed - you explicitly requested it via -f flag

Why direct file access is safe:

  1. You explicitly specify the file path in the command
  2. Same security validation as tool calls (blacklist, whitelist, .squidignore)
  3. Path validation happens before file is read
  4. Clear error messages if access is denied

Key difference from tool calls:

  • Tool calls: LLM decides what to read β†’ validation β†’ user approval β†’ read
  • Direct access: You decide what to read β†’ validation β†’ read (no approval needed since you chose the file)

Best Practices

βœ… DO

  • Review file paths carefully before approving read operations
  • Check content previews for write operations
  • Deny suspicious requests - You can always run the command again
  • Use absolute paths when possible to avoid ambiguity
  • Enable debug logging if you want more detailed information:
    RUST_LOG=debug squid ask "your question"

❌ DON'T

  • Blindly approve all tool executions
  • Allow reads of sensitive files (.env, private keys, passwords)
  • Approve writes without checking the content preview
  • Ignore unexpected tool requests - If you didn't expect file access, press N

Security Scenarios

Scenario 1: Preventing Sensitive File Access

Command:

squid ask "What environment variables do I have?"

LLM may try:

Tool: read_file
Path: .env

What happens:

  1. LLM requests to read .env (doesn't know it's blocked)
  2. Path validation checks .env against .squidignore
  3. .env is blocked automatically (in default .squidignore)
  4. You are NOT prompted - access denied immediately
  5. LLM receives friendly message: "I cannot access '.env' because it's protected by the project's .squidignore file. This is a security measure to prevent access to sensitive files."
  6. LLM relays the message to the user
  7. Your sensitive data stays protected without user interaction needed

Note: The LLM will still consume tokens for the initial request and the follow-up response, but no sensitive data is ever accessed.

Scenario 2: Validating Write Operations

Command:

squid ask "Create a startup script for this project"

LLM may try:

Tool: write_file
Path: startup.sh
Content: #!/bin/bash
rm -rf / # Malicious content

Your response:

  • Review the content preview
  • See the malicious rm -rf / command
  • Press N to deny
  • File is not created

Scenario 3: Safe Batch Operations

Command:

squid ask "Read all .rs files in src/ and create a summary"

LLM behavior:

  • Requests to read each file individually
  • Path validation passes for project files
  • You approve each one: src/main.rs βœ“, src/lib.rs βœ“, etc.
  • If LLM tries to read ignored files (e.g., target/), they're blocked automatically
  • Finally requests to write summary.txt
  • Path validation passes, you review the summary content
  • Approve if it looks correct

Logging and Audit

All tool operations are logged at the INFO level. To view these logs:

# Default (shows INFO and above)
RUST_LOG=info squid ask "your question"

# Debug (shows all logs including tool details)
RUST_LOG=debug squid ask "your question"

# Only errors
RUST_LOG=error squid ask "your question"

Log examples:

[INFO] Tool call: read_file with args: {"path":"README.md"}
[INFO] Successfully read file: README.md (2847 bytes)
[INFO] Tool call: write_file with args: {"path":"summary.txt","content":"..."}
[INFO] Successfully wrote file: summary.txt (156 bytes)

Or when denied:

[INFO] Tool call: read_file with args: {"path":".env"}
[INFO] Tool execution skipped by user: read_file

Technical Details

Implementation

The security approval is implemented using the inquire library, which provides:

  • Cross-platform terminal prompts
  • Default to false (deny by default)
  • Clear yes/no options
  • Keyboard-only operation (Y/N keys)

Non-Interactive Mode

If squid is run in a non-interactive environment (e.g., piped input, CI/CD), tool approval will fail with an error:

[ERROR] Failed to get user approval: not a terminal

This is intentional - tools require human approval and cannot run unattended.

Security Layers Summary

Squid employs three layers of security for file operations:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Layer 1: Path Validation (Whitelist/Blacklist)      β”‚
β”‚ βœ“ Blocks system directories (/etc, /root, etc.)     β”‚
β”‚ βœ“ Blocks sensitive files (~/.ssh, ~/.aws, etc.)     β”‚
β”‚ βœ“ Only allows current directory and subdirectories  β”‚
β”‚ β†’ Automatic rejection, no user prompt               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Layer 2: Ignore Patterns (.squidignore)             β”‚
β”‚ βœ“ Blocks files matching .squidignore patterns       β”‚
β”‚ βœ“ Configurable per-project rules                    β”‚
β”‚ βœ“ Works like .gitignore                             β”‚
β”‚ β†’ Automatic rejection, no user prompt               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Layer 3: User Approval                              β”‚
β”‚ βœ“ Explicit Y/N prompt for each operation            β”‚
β”‚ βœ“ Content preview for write operations              β”‚
β”‚ βœ“ Full transparency of tool arguments               β”‚
β”‚ β†’ Manual approval required                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Example Flow:

squid ask "Read all files in my project and create a summary"

# Attempt 1: Read ~/.ssh/id_rsa
# β†’ Layer 1 blocks (blacklisted path)
# βœ— Automatic rejection

# Attempt 2: Read node_modules/package/index.js  
# β†’ Layer 2 blocks (in .squidignore)
# βœ— Automatic rejection

# Attempt 3: Read src/main.rs
# β†’ Layers 1&2 pass
# β†’ Layer 3 prompts user
# ? Allow reading file: src/main.rs? (Y/n)

Future Enhancements

Potential future security features (not yet implemented):

  • Automatic approval for specific safe operations
  • Audit log file for all tool executions
  • Configuration option to disable tools entirely
  • Sandboxing or restricted file system access
  • Rate limiting for tool calls
  • Custom whitelist paths via configuration

Reporting Security Issues

If you discover a security vulnerability in squid, please report it responsibly:

  1. DO NOT create a public GitHub issue
  2. Contact the maintainer directly (see Cargo.toml for author email)
  3. Provide detailed information about the vulnerability
  4. Allow time for a fix before public disclosure

Summary

The security system in squid provides:

βœ… Path Validation - Automatic blocking of system and sensitive directories
βœ… Ignore Patterns - Project-specific file blocking via .squidignore
βœ… User Control - Final approval for every file operation
βœ… Transparency - See what's being accessed and written
βœ… Logging - Complete audit trail of all operations
βœ… Prevention - Multi-layered defense against unintended or malicious actions

Your security is our priority. Use squid with confidence knowing you're protected at multiple levels.

There aren’t any published security advisories