Write a policy HCL file that grants read/list on a path but denies access to a sub-path using the 'deny' capability: path 'secret/data/team/*' { capabilities = ["read", "list"] } path 'secret/data/team/restricted/*' { capabilities = ["deny"] }
Add a required_parameters constraint to prevent writes without a mandatory field: path 'secret/data/app/+/config' { capabilities = ["create", "update"] required_parameters = ["environment"] }
Add an allowed_parameters block to whitelist specific key-value pairs: path 'auth/approle/role/+/secret-id' { capabilities = ["update"] allowed_parameters = { "metadata" = [] } }
Write the policy to Vault: 'vault policy write myteam-policy myteam-policy.hcl'
Assign the policy to an AppRole token: 'vault write auth/approle/role/myapp token_policies=myteam-policy'
Test with 'vault token create -policy=myteam-policy' and attempt access to both the allowed and denied paths to verify
Known gotchas
The 'deny' capability takes precedence over all other capabilities on the same path even if the token has multiple policies that grant access — 'deny' is an absolute block
The '+' glob matches exactly one path segment; '**' or '*' at the end matches any suffix; mixing them incorrectly produces unintended path scopes
required_parameters only applies to create and update operations; a read request that doesn't send parameters is unaffected, which surprises operators expecting it to gate reads
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp