Protected Paths

Block agents from modifying sensitive files and directories

File tools reject writes to sensitive paths — .env, SSH keys, the SDK, and system files — and follow symlinks so a harmless.txt → .env link is still blocked.

python
from praisonaiagents import Agent
from praisonai.code.tools import write_file

agent = Agent(
    name="SafeCoder",
    instructions="Edit project files only. Never touch system paths.",
    tools=[write_file],
)

agent.start("Append 'test' to /etc/passwd")
# Tool returns: Path '/etc/passwd' is protected

The user asks the agent to change files; protected-path rules block dangerous writes before the tool runs.

Diagram

yes

no

Tool call

Protected?

Block

Run

How It Works

Diagram
ProtectedPathsAgentUserProtectedPathsAgentUserRequestProcessResultResponse

Quick Start

  1. Simple Usage

    Protected-path checks apply automatically when using praisonai code tools:

    python
    from praisonaiagents import Agent
    from praisonai.code.tools import write_file
    
    agent = Agent(name="Coder", instructions="Edit safely", tools=[write_file])
    agent.start("Write hello to src/app.py")
  2. With Configuration

    Inspect protection before a write:

    python
    from praisonai.security import is_protected, get_protection_reason, resolve_real_path
    
    if is_protected(".env"):
        print(get_protection_reason(".env"))
    # Environment file containing secrets

How It Works

Diagram
Protected PathsAgentUserProtected PathsAgentUserRequestProcess requestResultResponse

is_protected() and get_protection_reason() in praisonai.security.protected guard write_file, append_to_file, search_replace, apply_diff, and multiedit. They also drive the file-discovery tools glob_files, glob_directories, and grep_search. Both resolve symlinks (os.path.realpath) before matching, so a same-directory symlink to a protected file is checked by its real target, not its name.

Protected targets include environment files, .git/, SSH keys, ~/.aws/, /etc/passwd, praisonaiagents/, and audit.jsonl.

How it applies to each tool

Protection means refuse-write, skip-read, or hide depending on the tool.

ToolBehavior on protected path
write_file, append_to_file, search_replace, apply_diff, multieditRefuse-write, return error
grep_searchSkip during scan (protected files are never opened or read)
glob_files, glob_directoriesFilter out of the listing

multiedit (in praisonai.tools.multiedit) refuses protected files even when they sit inside the workspace root, returning: "Refusing to edit protected path: <reason>". grep_search (in praisonai.tools.grep_tool) skips protected files during its scan, and glob_files / glob_directories (in praisonai.tools.glob_tool) filter protected paths out of their results. See File Tool Workspace Confinement for how these tools also honour PRAISONAI_WORKSPACE.

Symlinks are resolved before matching — a symlink to a protected file is protected. is_protected() and get_protection_reason() call os.path.realpath() on the input first, so a same-directory harmless.txt → .env symlink is blocked as .env (PR #3616).

The protected-path check runs before workspace confinement — both apply to every write. See Code Editing → Workspace Security.

Blocked calls return:

python
{"success": False, "error": "Path '/etc/passwd' is protected: <reason>"}

Configuration Options

FunctionReturnsDescription
is_protected(path)boolWhether the path is blocked (symlink-resolved)
get_protection_reason(path)`str \None`Human-readable reason (symlink-resolved)
is_protected(path, extra_protected=[...])boolAdd project-specific paths
resolve_real_path(path)strSymlink-resolved absolute path; falls back to input on OSError

Symlink-safe writes

write_file, append_to_file, apply_diff, and search_replace resolve symlinks before both the protection check and the write. A same-directory symlink like harmless.txt → .env is refused with the same reason as .env itself, and a symlink that changes target between the check and the write cannot redirect an approved edit into a protected file.

python
from praisonai.security import resolve_real_path, is_protected

real = resolve_real_path("./harmless.txt")   # → "/…/.env"
is_protected(real)                            # → True

Best Practices

Never disable in production

Protected-path checks are a safety default — extend extra_protected only after review.

Use praisonai code tools

Protection is enforced in praisonai.code.tools, not the core FileTools class.

Check before custom tools

Call is_protected() in custom write tools that bypass the built-in guards.

Keep secrets out of prompts

Even with protection, avoid passing .env contents into agent context.


Related