Policy reference
Every key a Vardhold policy accepts. Policies are plain YAML, validated with line-numbered errors before they apply.
File layout#
version: 1 # required, always 1
mode: enforce # monitor | enforce | strict (default enforce)
rules: # read top to bottom; the first match decides
- id: ...An action that no rule matches is logged, except in strict mode, where an unmatched action checked before it runs needs approval.
Rule keys#
| Key | Value | Meaning |
|---|---|---|
id | 1–100 characters: letters, digits, . _ - | Required. Names the rule in prompts, events and the audit log. |
description | Text | Shown to people deciding approvals and reading events. |
enabled | true | false | Default true. A disabled rule never matches. |
match | Mapping, below | What the rule applies to. Every key given must match; no match matches everything. |
verdict | allow | log | ask | block | Required. The decision. |
verdict_strict | A verdict | Replaces verdict in strict mode. |
verdict_trusted | A verdict | Replaces verdict for agents marked trusted. |
severity | info | low | medium | high | critical | Default info. Carried into events and the SIEM. |
alert | true | false | Raise an alert when the rule matches, whatever the verdict. |
timeout_seconds | 5–3600 | For ask: how long to wait for a person. Without it, the approvalTimeoutSeconds setting applies. |
on_timeout | block | allow | For ask: what happens if nobody answers. Default block. |
Match keys#
All match keys are optional. A key that takes a list also accepts a single value.
| Key | Matches |
|---|---|
agent | Agent ids, with * wildcards: claude-code, cursor, mcp:github, mcp:* |
action | One or more actions |
path | Files or folders, as path patterns |
path_not | Exceptions: the rule does not match these paths |
outside_cwd | true: the path is outside the agent's working folder. false: inside it. |
command_regex | A regular expression (case-insensitive) tested against the command line |
host | Host names for net.connect, with * wildcards: *.github.com |
host_not_in | Matches hosts not in a list, given inline or as a file of one pattern per line |
first_contact | true: the first time this agent has contacted this host |
tool | MCP tool names (without the server), with wildcards: *exec*, create_*. Combine with agent: mcp:github for one server. |
target | The raw target (command, path, host or server/tool), with wildcards |
Actions#
| Action | Target | Checked before it runs |
|---|---|---|
shell.exec | The command line | Claude Code, Cursor |
process.start | The command line of a process an agent started | Recorded as it happens |
file.read | The file path | Claude Code, Cursor, MCP arguments |
file.write | The file path | Claude Code, Cursor, MCP arguments; also recorded as it happens |
file.delete | The file path | Cursor; also recorded as it happens |
net.connect | The host | Agent web tools; also recorded as it happens |
mcp.call | server/tool, with the arguments checked too | Every MCP server behind the proxy |
Events also carry system actions such as agent.discovered, approval.decided, policy.changed, killswitch, integration.unprotected, audit.anchor and audit.integrity. Rules do not usually match them, but they appear in the timeline and the SIEM.
Verdicts#
| Verdict | Before it runs | As it happens |
|---|---|---|
| allow | Runs, not alerted | Recorded |
| log | Runs, recorded | Recorded |
| ask | Waits for a person | Recorded with its verdict |
| block | Does not run; the agent is told why | Alert raised; headless agents can be suspended automatically |
Modes#
monitor: rules match and alerts fire, but nothing is blocked or held.enforce: rules apply as written.strict:verdict_strictapplies where a rule sets one, and checked actions that no rule matches need approval.
Path patterns#
| Pattern | Matches |
|---|---|
** | Any number of folders. dir/** also matches dir itself. |
* | Anything within one folder name |
? | One character |
*.pem | A pattern without a slash matches the file name only, in any folder |
~, %USERPROFILE%, %APPDATA%, %LOCALAPPDATA%, %PROGRAMDATA% | Expanded for the user the agent runs as |
Use forward or back slashes; matching ignores case. Paths are compared the way Windows resolves them: .. and . are resolved, symbolic links, junctions and 8.3 short names are followed, and administrative shares, \\?\ prefixes, data streams and trailing dots are handled. Shell commands are also checked as the files they name.
The default policy#
New installs start with these rules, in this order. Edit or extend them like any other rule.
| Rule | Verdict | Protects |
|---|---|---|
protect-vardhold-files | block | Vardhold's own policy, data and program files |
protect-agent-hooks | block | The hook registrations that let Vardhold check agents |
protect-vardhold-service | block | The Vardhold service, against being stopped, reconfigured or removed by an agent |
protect-ssh-keys | block | SSH keys and cloud, Kubernetes, Docker, git and npm credentials |
protect-browser-data | block | Browser profiles: cookies and saved passwords |
credential-manager | block | Windows Credential Manager and credential-dumping tools |
env-and-keys-outside-project | ask | .env files and private keys outside the current project |
confirm-recursive-delete | ask | Recursive deletes, disk formatting and git history rewrites |
persistence-autorun | ask | Autorun registry keys and scheduled tasks |
defender-tampering | block | Windows Defender and the firewall, against being turned off |
first-contact-egress | log + alert | An agent contacting a host it has never contacted before (ask in strict mode) |
mcp-shell-tools | ask | MCP tools that run arbitrary shell commands |
project-work | log | Reading and editing inside the current project |
Ask rules in the default policy wait 60 seconds and then block.