Policy Rules
Block tools, arguments, and outcomes from natural-language commands
Policy Rules
Control what tools Copilot can use, right from the chat prompt. Policy rules are evaluated before intent plans. A denied tool stays denied even if Copilot declared it in the plan.
Commands
| Command | Example |
|---|---|
| Create a rule | Policy new: deny webfetch |
| List all rules | Policy list |
| View one rule | Policy get policy1 |
| Delete a rule | Policy delete policy1 |
| Clear all rules | Policy reset |
| Modify a rule | Policy update policy1: allow webfetch |
| Reorder rules | Policy prioritize policy2 1 |
| Show help | Policy help |
How Rules are Evaluated
- Rules evaluate top-to-bottom in the order they appear
- First matching rule wins (deny, allow, or require_approval)
- No match means allow (default-open for local policies)
New rules are added at the top, giving them the highest priority.
Writing effective policies: block outcomes, not just tools
This is the most important section in this guide. Denying a single tool is necessary but not sufficient because Copilot's planner can often route around a single block by using a different tool to achieve the same outcome.
Real example we saw
> Policy new: deny webfetch
✔ Policy updated. Version 1.
> fetch https://example.com
● Register Intent Plan ...
● Fetch https://example.com with curl (shell)
│ curl -sS https://example.com
└ <!doctype html>...
● Fetched via curl (web_fetch is denied by policy).ArmorCopilot did exactly what you told it: blocked web_fetch. But Copilot annotated "web_fetch is denied by policy" and switched to the shell tool with curl. The outcome (fetching the URL) happened anyway.
This is not a bypass. It's a policy authoring problem. The fix is to write broader rules that cover the OUTCOME you actually want blocked.
Pattern 1: Block multiple tools
> Policy new: deny webfetch
> Policy new: deny websearch
> Policy new: deny shell when args contain "curl"
> Policy new: deny shell when args contain "wget"
> Policy new: deny shell when args contain "nc "Now Copilot can't fetch URLs via web_fetch, can't search the web, and can't shell out to curl / wget / nc.
Pattern 2: Match on argument patterns
Rules can match on tool arguments, not just tool names:
> Policy new: deny shell when args contain "http://"
> Policy new: deny shell when args contain "https://"This blocks any shell command that includes a URL. Covers not just curl and wget but git clone https://..., pip install https://..., anything that touches a URL.
Pattern 3: Block data exfiltration broadly
If your concern is "no data leaves the machine":
> Policy new: deny webfetch
> Policy new: deny websearch
> Policy new: deny shell when args contain "curl|wget|nc |scp |rsync |ssh "
> Policy new: deny shell when args contain "@" and contain "."The last rule catches anything that looks like an email address or remote scp target (user@host:).
Pattern 4: Block writes outside a sandbox
> Policy new: deny write when path not starts with "/tmp"
> Policy new: deny shell when args contain "rm -rf"Pattern 5: Sensitive-data classification
ArmorCopilot auto-detects sensitive data in tool arguments using the built-in ArmorIQ data classifier:
| Class | What it detects |
|---|---|
| PCI | Credit card numbers (Luhn-validated), card-related keywords |
| PAYMENT | Payment tool names, banking keywords (IBAN, SWIFT, routing) |
| PHI | Health/medical data |
| PII | Personal data, SSN |
Use it to block by data class instead of tool name:
> Policy new: deny * for payment data
> Policy new: deny webfetch for PIIIf Copilot tries to send a credit card number anywhere, ArmorCopilot detects PCI, matches the rule, and blocks the tool call.
Recommended starter policy
If you want a sensible default that catches the common LLM-routing-around-single-blocks cases, set this up at the start of every session:
> Policy new: deny webfetch
> Policy new: deny websearch
> Policy new: deny shell when args contain "curl|wget|nc "
> Policy new: deny shell when args contain "http://|https://"
> Policy new: deny shell when args contain "rm -rf /"
> Policy new: deny * for payment dataSix rules cover: network egress via dedicated tools, network egress via shell, destructive deletes, and PCI exfiltration. Add more as needed for your workflow.
Agent-Managed Policies
When ArmorCopilot blocks a tool, Copilot sees the denial and may ask:
"The web_fetch call was blocked by policy1. Would you like me to update the policy to allow it?"
If you say yes, Copilot calls the policy_update MCP tool to modify or delete the rule, then retries. This is safe because policy_update is whitelisted (never blocked by intent enforcement) and the policy change is recorded in the audit log.
Where Policies are Stored
Policies persist across sessions in the plugin data directory:
cat ~/.copilot/armorcopilot/policy.jsonThey survive restarts, plugin updates, and re-installs. To wipe them: Policy reset or rm the file.
Companion config
| Where | What |
|---|---|
~/.copilot/armorcopilot/policy.json | Active rules + version |
~/.copilot/armorcopilot/audit/ | Pre-flush audit WAL |
~/.copilot/armorcopilot/pending-plan.<sessionId>.json | Per-session pending intent plan |
~/.copilot/armorcopilot/runtime.json | Session state |
~/.armoriq/credentials.json | ArmorIQ API key (if connected) |
See Configuration for env var overrides.