← All docs

Default policies

Policy rulesets shipped with agentjail: file, command, mcp, web, internal tools, and locked self-protection rules.

When you install agentjail, several core policy rulesets are embedded in the binary via go:embed. You do not have to write a single rule to be protected from the most common dangerous tool calls.

The embedded sources live in the repository under:

  • cmd/agentjail/policies/: core rules (file_policy.rego, command_policy.rego, mcp_policy.rego, web_policy.rego, internal_tools.rego)
  • cmd/agentjail/library/: optional library rules that can be enabled/disabled

file_policy

rule_id prefix: file_policy/

Enforces two tiers of protection for file access (Read, Write, Edit, Bash):

Hard deny everywhere (regardless of working directory)

These paths and patterns are always denied, no matter where the agent is working:

Directories

PathNotes
~/.sshSSH keys and known hosts
~/.awsAWS credentials and config
~/.gnupgGPG keyring
~/DownloadsBrowser download folder - see note below
~/DesktopDesktop folder
~/.agentjailagentjail config and rules (see file_policy/agentjail_self below)
~/.configXDG user config directory
/etc and /private/etcSystem configuration
/var and /private/var (non-temp)System variable data

Credential-token stores (home-anchored)

PathNotes
~/.npmrcnpm auth token
~/.pypircPyPI upload credentials
~/.git-credentialsGit credential store (tokens in URLs)
~/.docker/config.jsonDocker registry auth
~/.kube/configKubernetes cluster credentials
~/.cargo/credentials (and .toml)crates.io token
~/Library/KeychainsmacOS keychain databases

Sensitive basenames: ask inside project dir, deny outside

Files matching these patterns are asked when they are inside the granted project working directory, and denied everywhere else:

PatternNotes
.env and .env.*Environment variable files
.envrcdirenv config
credentials or secrets (any file named exactly)Generic credential files
*.pem, *.key, *.p12, *.pfx, *.jks, *.keystoreCryptographic key material
.netrcMachine credentials file
id_rsa, id_ed25519, id_ecdsa, id_dsaSSH private key files

Project membership is boundary-safe (path == cwd OR startswith(path, cwd + "/")), so a sibling directory like /proj2 never matches cwd=/proj.

~/Downloads: ask for media, deny for credentials

~/Downloads is no longer a hard deny. The file_policy/downloads_review rule fires an ask for non-sensitive files (e.g. .srt, .pdf, .png, .mp4, downloaded source archives). The agent must get explicit confirmation before reading or writing anything in that directory.

Files in ~/Downloads that match the sensitive-basename patterns (.pem, .env, id_rsa, etc.) still trigger the standard deny via file_policy/sensitive_credential, exactly as they would anywhere else outside the project directory.

Temp tree is allowed

The temp tree ($TMPDIR, /tmp, /var/folders/…) is allowed. Agents can freely read and write temporary files.

file_policy/agentjail_self (locked)

Writes to ~/.agentjail/ get their own hard-deny rule (file_policy/agentjail_self). This rule is part of the locked self-protection set and cannot be disabled.

command_policy

rule_id prefix: command_policy/

Enforces safe command patterns regardless of file paths. Verdicts are deny or ask (confirm before proceeding).

Denied (blocked outright)

PatternReason
curl or wget piped into bash or shRemote code execution via download
Any command containing sudoPrivilege escalation
dd if=/dev/*Raw device write
chmod 777World-writable permission grant
Redirect to block device (> /dev/disk*, /dev/sd*, /dev/nvme*, /dev/mmcblk*)Overwrite block device
rm -rf on absolute paths (except the temp tree)Destructive recursive delete
git push --force to main/masterDestructive history rewrite on the default branch
env or printenv piped to curlEnvironment variable exfiltration
gpg --export-secret-keysSecret key export
launchctl bootout or launchctl removemacOS service removal
systemctl stop or systemctl disableLinux service shutdown
ssh-keygen -f targeting a path outside /tmpKey generation outside temp dir
Any Bash command referencing a sensitive path listed in file_policyCross-policy enforcement

Requires confirmation (ask)

PatternReason
git push (non-force)Remote repository write
git push --force with no explicit branch (git push -f)Target is the implicit current branch; confirm it is not the default branch
npm/yarn/pnpm publish, cargo publish, pip upload, twine upload, gem push, poetry publish, docker push, gh release createPackage / image / release publish
curl -O downloading to a path other than /tmpPersistent file download

Force-push branch awareness

command_policy distinguishes three cases for git push --force (or -f / --force-with-lease / +<refspec>):

  • Deny - the command names main or master (e.g. git push origin main --force, git push --force-with-lease origin +main). Rewrites shared history.
  • Allow - the command names an explicit non-default branch (e.g. git push origin my-feature -f). Normal rebase / PR-update workflow.
  • Ask - the command contains a force flag but no explicit branch (git push -f). The daemon cannot read the current branch from the command string, so it asks rather than guessing.

command_policy/no-policy-mutation (locked)

An always-on, locked rule blocks an agent from running agentjail policy disable, agentjail mcp, or writing into ~/.agentjail/. This is part of the locked self-protection set and cannot be disabled.

Always-on self-protection rules (locked)

In addition to the core rulesets above, two rules guard agentjail itself and are part of the locked set, they can never be disabled:

Rule IDWhat it blocks
library/no-daemon-killkill/pkill/killall targeting agentjail-daemon
library/no-hook-self-disableWrites to ~/.claude/, ~/.codex/, ~/.cursor/ settings (an agent removing its own hook)

These rules are always-on core rules, not opt-in. They appear as locked in agentjail policy list.

mcp_policy

rule_id prefix: mcp_policy/

Controls which MCP servers the agent is permitted to call.

Trust-on-install: when you run agentjail install, the installer automatically seeds mcp.allowed in policy.yaml from the MCP servers already configured in your agents (Claude/Codex/Cursor), so existing servers like claude-mem, context7, or github keep working immediately.

Default blocklist: *stripe*, *payment*, *billing*, *twilio*, *sendgrid* are always blocked. The blocklist always takes precedence over the allowlist.

Server-level controls

Manage with agentjail mcp:

agentjail mcp list                 # current allowed + blocked
agentjail mcp allow claude-mem     # trust a server
agentjail mcp block my-payment-bot # block a server

Or edit ~/.agentjail/policy.yaml directly:

mcp:
  allowed: ["claude-mem", "context7", "github*"]
  blocked: ["*stripe*", "*payment*"]

Per-tool granular controls (v0.2.8+)

Beyond server-level allow/block, you can gate individual tools within an allowed MCP server using blocked_tools and ask_tools:

mcp:
  allowed: ["github"]
  blocked_tools: ["github/delete_repo", "github/transfer_repo"]
  ask_tools: ["github/create_repo"]

Manage via CLI:

agentjail mcp tool allow github/list_repos
agentjail mcp tool block github/delete_repo
agentjail mcp tool ask github/create_repo

MCP inventory (v0.2.9+)

Get a full picture of every MCP server across your team:

agentjail mcp inventory

Scans agent configs (Claude, Codex, Cursor), npm packages, pip packages, and Docker containers for MCP servers. Each entry includes provenance metadata and a security audit flag.

Per-project policy (v0.2.9+)

Policies cascade from global defaults to per-project overrides. Use the web UI project selector or configure in policy.yaml:

projects:
  /path/to/project:
    mcp:
      allowed: ["project-specific-server"]
      blocked: ["*billing*"]

Per-skill controls (v0.2.9+)

Gate agent skills with the same allow/block/ask model:

agentjail skill allow code-review
agentjail skill block deploy-to-prod
agentjail skill ask run-migration

web_policy

rule_id prefix: web_policy/

Governs the agent’s read-only web tools (WebSearch and WebFetch). Without this policy every web call would fall through to resolver/defaultask, creating constant noise for what is, in the common case, a benign read.

ToolDefault verdictRule ID
WebSearchallow (always)web_policy/search
WebFetchallow (read-only GET)web_policy/fetch
WebFetch to a blocked hostdenyweb_policy/fetch_blocked

WebSearch is a query to the agent harness’s own search backend, not an arbitrary endpoint, so it is always allowed unconditionally.

WebFetch is an HTTP GET and is allowed by default. You can block specific hosts via glob patterns in policy.yaml:

web:
  blocked: ["*.internal", "169.254.*", "*tracking*"]

The web.blocked globs match the hostname only (not the path). Use * to span subdomains (*.corp.internal or *tracking*). Disabling web_policy/fetch (via disabled_rules) reverts WebFetch to ask.

internal_tools

rule_id prefix: internal_tools/

Auto-allows agent harness tools that have no external side effects. Without this policy, every orchestration call (task management, plan mode, tool-schema lookup, etc.) would escalate to the user - pure noise.

Harness-internal tools (internal_tools/allow) - manage in-session state only; never touch the filesystem, shell, network, or MCP servers:

CategoryTools
Task/plan managementTaskCreate, TaskUpdate, TaskGet, TaskList, TaskOutput, TaskStop, TodoWrite, EnterPlanMode, ExitPlanMode, UpdatePlan, update_plan
Tool schemaToolSearch
Worktree/orchestrationLSP, CronCreate, CronDelete, CronList
MessagingSendMessage, ScheduleWakeup, DesignSync
OtherAskUserQuestion

Benign tools (internal_tools/benign_allow) - touch the filesystem or shell only in ways that are already governed or have no new side effect:

ToolWhy it is safe
GlobRead-only path enumeration (returns paths, not file contents)
BashOutputReads stdout/stderr of an already-approved background shell
KillShellTerminates an agent-spawned background shell by session ID
Task / AgentDispatches a subagent - the subagent’s own tool calls fire this same hook and are independently governed
SkillLoads a skill’s instructions; anything it then executes (Bash, Read/Write) fires this hook too
WorkflowOrchestrates multi-agent workflows; subagent calls are independently hooked
EnterWorktreeCreates a git worktree for isolated work; tool calls within the worktree are independently hooked
ExitWorktreeExits/cleans up an agent-owned worktree

Tools deliberately not covered here (they keep normal governance because they have real, ungoverned side effects): Bash, Read, Write, Edit, NotebookEdit, MCP resource tools, and all MCP server tools. Grep is also excluded intentionally - it returns file contents and would bypass file_policy’s sensitive-path deny.

Library rules (opt-in)

Shipped but not loaded by default: enable per your threat model with agentjail policy enable <name>. They block behavior that is suspicious in most contexts but legitimately used in some workflows, so they are opt-in to keep the core rules false-positive-free.

Rule IDWhat it blocks
library/no-shell-init-writeWrites to shell init files (~/.zshrc, ~/.bashrc, …): persistence
library/no-app-binary-writeWrites into installed /Applications/*.app bundles
library/no-launchctllaunchctl submit/load, osascript, at, crontab -e/-r: out-of-tree process spawn
library/no-history-readReads of shell histories + browser cookies/history
library/no-shell-evaleval, bash -c $VAR, base64-decode pipelines: obfuscated execution
library/no-destructive-gitWhole-tree git reset --hard, git clean -fdx, git restore . (single-file ops stay allowed)

Rule IDs use the hyphenated form (e.g. library/no-shell-init-write) in rule_id fields and disabled_rules config. When passing names to agentjail policy enable/disable, both the hyphenated form and the underscore stem are accepted (e.g. no_shell_init_write or no-shell-init-write).

Disabling rules and the locked set

Any rule that is not in the locked set can be suppressed:

agentjail policy list                                 # on / off / locked for every rule
agentjail policy disable file_policy/sensitive_in_project  # stop asking on in-project secrets
agentjail policy enable  file_policy/sensitive_in_project  # turn it back on

Disabling a core rule requires --force and an interactive TTY confirmation: an agent cannot do this non-interactively. All mutations are logged to ~/.agentjail/audit.log.

The following locked self-protection set can never be disabled by policy.yaml edit or CLI, regardless of --force:

  • file_policy/agentjail_self
  • library/no-daemon-kill
  • library/no-hook-self-disable
  • command_policy/no-policy-mutation
  • resolver/*

Verdicts

All rulesets produce one of three verdicts via the candidate → resolver → decision model:

VerdictMeaning
allowTool call proceeds immediately.
askThe agent is prompted to confirm before continuing.
denyTool call is blocked; the agent receives a rejection message.

The fail-safe default (no candidates fire) is ask.

Reading the source

All shipped rules are plain Rego that you can audit before running. The canonical source is the agentjail repository on GitHub:

github.com/LuD1161/agentjail

The core rules are in cmd/agentjail/policies/ and library rules are in cmd/agentjail/library/.

Verifying what is active

Run agentjail policy list to see which rulesets are currently loaded:

agentjail policy list
RULE                                   STATUS   SOURCE
file_policy/sensitive_credential       locked   Core
command_policy/no-sudo                 on       Core
library/no-shell-init-write            off      Optional

Core rules always show status on or locked. Library rules that you have enabled appear with status on. See the CLI reference for full policy list, policy enable/disable, policy add/remove, and mcp documentation.

Extending the defaults

The default bundle is a starting point. You can add your own Rego rules using agentjail policy add (recommended: validates the authoring contract and hot-reloads the daemon), or by dropping a .rego file into ~/.agentjail/rules/ and sending SIGHUP. See Writing your first rule to get started.