VMware Policy
Author: Wei Zhou, VMware by Broadcom — wei-wz.zhou@broadcom.com This is a community-driven project by a VMware engineer, not an official VMware product. For official VMware developer tools see developer.broadcom.com.
Unified audit logging, policy enforcement, and sanitization for the VMware MCP skill family.
Install
pip install vmware-policy
Usage
from vmware_policy import vmware_tool
@vmware_tool(risk_level="high", sensitive_params=["password"])
def delete_segment(name: str, env: str = "") -> dict:
...
Reporting a failure the tool returns
Most tools signal failure by raising, and @vmware_tool records that. A tool that
instead catches the exception and returns an error payload looks identical to a
successful call — and for a long time was recorded as one, which also meant undo
tokens were written for changes that never happened and the circuit breaker never
saw a failure.
Dict-shaped payloads are now detected automatically. Nothing to do if a tool returns the family shape:
return {"error": msg, "hint": "Run 'vmware-nsx doctor'."} # audited as a failure
A tool whose return type cannot carry that marker — one handing back console text, say — must say so explicitly:
from vmware_policy import report_tool_failure
except Exception as exc:
report_tool_failure(str(exc))
return f"Error: {msg}"
Strings are deliberately not sniffed: skills that return console output can emit text beginning with "Error:" as data, and marking those calls failed would be the same misreport in the opposite direction.
CLI
vmware-audit log --last 20
vmware-audit log --status denied --since 2026-03-28
vmware-audit stats --days 7
vmware-audit policy # which rules are in force
Components
| Component | Description |
|---|---|
@vmware_tool |
Decorator around a skill's MCP tools -- policy pre-check + execute + audit row |
AuditEngine |
Append-only SQLite (WAL) audit log; rotates at 100 MB, keeps 5 archives |
PolicyEngine |
YAML rules: deny rules and maintenance window, hot-reloaded on file change. change_limits is reserved and not enforced. |
sanitize() |
Prompt-injection defense -- strips C0/C1 control and Unicode format characters, truncates (default 500 chars) |
vmware-audit |
Typer CLI -- query, export, statistics, rule status |
AI Agent -> vmware-pilot (optional orchestration) -> @vmware_tool pre-check -> skill operation -> audit row -> ~/.vmware/audit.db
Policy rules
Read/write authorization belongs to the vCenter/NSX account's RBAC. The policy
engine only adds the operator's own deny rules and maintenance window, from
~/.vmware/rules.yaml ($OPS_HOME/rules.yaml if set). vmware-audit policy
reports which source is in force:
| Source | When | What is permitted |
|---|---|---|
user |
Your rules file exists and loads | Whatever your rules allow |
packaged-default |
No rules file | The shipped baseline, which denies nothing -- all operations are allowed by policy |
user-unreadable |
Your file exists but will not load (YAML error, not UTF-8) | Nothing -- every operation is denied until it loads; the baseline is never substituted |
baseline-unreadable |
No user file and the shipped baseline will not load | Nothing -- every operation is denied |
PyYAML is a declared dependency; if it is missing, decorated tool calls fail rather than run. Rules hot-reload on file change.
VMWARE_POLICY_DISABLED=1 is an operator escape hatch: in the process that has
it set (the MCP host, or a CLI shell) every policy check is skipped, including
the unreadable-rules denial. Auditing continues -- each bypassed check logs a
warning, and rows from both surfaces -- @vmware_tool MCP calls and @guarded
CLI commands -- are recorded with a _bypassed status suffix (ok_bypassed,
error_bypassed). Restrict who can set the MCP host's environment.
Risk levels
The level a tool declares is recorded in the audit row, can be matched by a
deny rule's min_risk_level, and decides whether a configured maintenance
window applies. It does not by itself gate execution.
| Level | Examples |
|---|---|
low |
list, get, info, status |
medium |
reconfigure, update |
high |
power off, migrate, snapshot revert |
critical |
delete VM, delete cluster |
Security
- The audit database (
~/.vmware/audit.db, local only,0700directory /0600files) records tool parameters, results, status, OS user and inferred agent -- treat it and its archives as sensitive. - Parameters named in
sensitive_paramsare stored as***; results from tools declaringsensitive_result=Trueare replaced; credential-named keys (password,token,kubeconfig, ...) in parameters and results, and credential-shaped text in error messages, are redacted on both the MCP and CLI surfaces. A credential under a key name not on that list must be declared insensitive_params. sanitize()guards against prompt injection through API response text.- Policy bypass (
VMWARE_POLICY_DISABLED=1) skips policy checks, not auditing.
Metadata
Release files for vmware-policy 1.15.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vmware_policy-1.15.0.tar.gz | 181.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vmware_policy-1.15.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 251.0 kB
Release files / vmware_policy-1.15.0.tar.gz
| Download URL | vmware_policy-1.15.0.tar.gz |
|---|---|
| Size | 181.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
48e1850c434dd3f34401b1e3785c073d72b451af904cc2f8c7d3bde772309e8a
|
|
BLAKE2b-256 checksum How to use checksums |
ac0cc7b6c9e2e82b5c8d40b0721bfc9a6428bdd9fd41d8c1c6ec492b94f183f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / vmware_policy-1.15.0-py3-none-any.whl
| Download URL | vmware_policy-1.15.0-py3-none-any.whl |
|---|---|
| Size | 69.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2f5a7b0e57fc084ea9083e67fb6e3c27059e6bd9c75b3eabfed58d6ee4366db4
|
|
BLAKE2b-256 checksum How to use checksums |
3726088f02325e51109cfe8e433d861c28f75f22ce26bb375944d365c46f85c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|