{"id":"f6b0ba48-2b1f-4bae-b0f6-74027239c954","entityType":"agent","slug":"clawhub-zw008-vmware-nsx-security","name":"vmware-nsx-security","canonicalUrl":"https://www.xpersona.co/agent/clawhub-zw008-vmware-nsx-security","canonicalPath":"/agent/clawhub-zw008-vmware-nsx-security","generatedAt":"2026-10-09T19:19:00.837Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:26:16.410Z","emptyReason":null},"description":"Use this skill whenever the user needs to manage VMware NSX security (rebranded VMware vDefend in VCF 9) — distributed firewall (DFW) policies, security groups, microsegmentation, and IDS/IPS. Directly handles: create/manage DFW policies and rules, security groups, VM tags, network traceflow diagnostics, IDPS profiles and status. Always use this skill for \"create firewall rule\", \"set up microsegmentation\", \"add VM to security group\", \"run traceflow\", \"check IDS status\", \"vDefend firewall rule\", or any NSX security / vDefend / DFW task. Do NOT use for NSX networking operations like segments, gateways, NAT, or routing (use vmware-nsx), or VM lifecycle (use vmware-aiops). For load balancing/AVI/AKO use vmware-avi.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 5.1K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:vmware-nsx-security","sourceUrl":"https://clawhub.ai/zw008/vmware-nsx-security","homepage":"https://clawhub.ai/zw008/skills/vmware-nsx-security","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/zw008/vmware-nsx-security","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/zw008/skills/vmware-nsx-security","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":49,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"vmware-nsx-security technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:26:16.410Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:26:16.410Z","emptyReason":null},"stars":null,"forks":null,"downloads":5050,"packageName":null,"latestVersion":"1.13.0","tractionLabel":"5.1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:26:16.410Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T04:26:16.410Z","lastCrawledAt":"2026-10-09T04:26:16.410Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T04:26:16.410Z","lastVerifiedAt":null,"highlights":[{"version":"1.13.0","createdAt":"2026-09-20T14:52:13.991Z","changelog":"MCP instructions now name the configured targets and how to choose one; a config that cannot be read says so instead of falling silent.","fileCount":8,"zipByteSize":27486},{"version":"1.12.0","createdAt":"2026-09-19T03:55:32.188Z","changelog":"Destructive MCP tools preview by default (confirm=False) and state their blast radius; confirm=True refuses on blockers or unreadable measurements. Requires vmware-policy>=1.17.0.","fileCount":8,"zipByteSize":27452},{"version":"1.11.1","createdAt":"2026-09-15T06:04:20.041Z","changelog":"CLI reads are audited under their MCP tool names; every CLI command declares what it reaches (needs vmware-policy 1.15.0)","fileCount":8,"zipByteSize":26455},{"version":"1.11.0","createdAt":"2026-09-12T00:19:39.317Z","changelog":"CLI writes are authorised and audited under their MCP tool names, and environment-scoped deny rules now apply to CLI writes as well as MCP tools.","fileCount":8,"zipByteSize":26461},{"version":"1.10.0","createdAt":"2026-09-02T14:42:40.594Z","changelog":"`tag remove` now confirms — a behaviour change for scripts","fileCount":8,"zipByteSize":26461},{"version":"1.9.2","createdAt":"2026-08-31T07:24:48.016Z","changelog":"one answer per .env, on every platform","fileCount":8,"zipByteSize":26354},{"version":"1.9.1","createdAt":"2026-08-31T00:37:59.790Z","changelog":"fix: run the suite on a non-UTF-8 machine, and stop one skill answering for another","fileCount":8,"zipByteSize":26287},{"version":"1.9.0","createdAt":"2026-08-30T15:18:44.374Z","changelog":"Second-round fixes from the 2026-08-30 VCF 9.1 re-test; vmware-policy floor raised to 1.11.0 (the engine no longer fails open when rules.yaml cannot be read).","fileCount":8,"zipByteSize":26332}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:vmware-nsx-security","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:vmware-nsx-security` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/zw008/vmware-nsx-security before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-09T19:19:00.833Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-nsx-security/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:26:16.410Z","emptyReason":null},"readme":"Skill: vmware-nsx-security\n\nOwner: zw008\n\nSummary: Use this skill whenever the user needs to manage VMware NSX security (rebranded VMware vDefend in VCF 9) — distributed firewall (DFW) policies, security groups, microsegmentation, and IDS/IPS. Directly handles: create/manage DFW policies and rules, security groups, VM tags, network traceflow diagnostics, IDPS profiles and status. Always use this skill for \"create firewall rule\", \"set up microsegmentation\", \"add VM to security group\", \"run traceflow\", \"check IDS status\", \"vDefend firewall rule\", or any NSX security / vDefend / DFW task. Do NOT use for NSX networking operations like segments, gateways, NAT, or routing (use vmware-nsx), or VM lifecycle (use vmware-aiops). For load balancing/AVI/AKO use vmware-avi.\n\nTags: latest:1.13.0\n\nVersion history:\n\nv1.13.0 | 2026-09-20T14:52:13.991Z | user\n\nMCP instructions now name the configured targets and how to choose one; a config that cannot be read says so instead of falling silent.\n\nv1.12.0 | 2026-09-19T03:55:32.188Z | user\n\nDestructive MCP tools preview by default (confirm=False) and state their blast radius; confirm=True refuses on blockers or unreadable measurements. Requires vmware-policy>=1.17.0.\n\nv1.11.1 | 2026-09-15T06:04:20.041Z | user\n\nCLI reads are audited under their MCP tool names; every CLI command declares what it reaches (needs vmware-policy 1.15.0)\n\nv1.11.0 | 2026-09-12T00:19:39.317Z | user\n\nCLI writes are authorised and audited under their MCP tool names, and environment-scoped deny rules now apply to CLI writes as well as MCP tools.\n\nv1.10.0 | 2026-09-02T14:42:40.594Z | user\n\n`tag remove` now confirms — a behaviour change for scripts\n\nv1.9.2 | 2026-08-31T07:24:48.016Z | user\n\none answer per .env, on every platform\n\nv1.9.1 | 2026-08-31T00:37:59.790Z | user\n\nfix: run the suite on a non-UTF-8 machine, and stop one skill answering for another\n\nv1.9.0 | 2026-08-30T15:18:44.374Z | user\n\nSecond-round fixes from the 2026-08-30 VCF 9.1 re-test; vmware-policy floor raised to 1.11.0 (the engine no longer fails open when rules.yaml cannot be read).\n\nv1.8.12 | 2026-08-30T09:34:56.770Z | user\n\nParameter descriptions now reach the MCP JSON schema (0% -> 100% coverage); additionalProperties closed; vmware-policy floor raised to 1.10.0.\n\nv1.8.11 | 2026-08-30T07:50:48.744Z | user\n\nrule_count was never requested from NSX, so every policy reported zero rules; paging loops now terminate via next_offset; verify_ssl:false no longer needs an undeclared urllib3.\n\nv1.8.10 | 2026-08-28T02:55:39.063Z | user\n\nFixes the server's self-reported version and the advertised tool count; adds a Claude Code plugin manifest.\n\nv1.8.9 | 2026-08-01T03:11:54.507Z | user\n\nMoved to vmware-skills GitHub org; MCP Registry namespace → io.github.vmware-skills. Links updated.\n\nv1.8.8 | 2026-07-21T15:44:30.059Z | user\n\nCLI writes now route through the shared guard()+audit_call() core via @guarded, exactly like the MCP tools (HLD I-1/I-8). Requires vmware-policy>=1.8.8.\n\nv1.8.7 | 2026-07-21T11:41:06.463Z | user\n\nRemove read-only switch and approval tiers; read/write authz delegated to RBAC. Plus accumulated fixes since 1.8.5.\n\nv1.8.5 | 2026-07-20T13:05:03.795Z | user\n\nA failure that is returned is now audited as a failure, and certificate/URL detail no longer reaches the agent. Both fixes v1.8.4 announced were incomplete.\n\nv1.8.4 | 2026-07-20T08:26:16.366Z | user\n\nTeaching error messages, domain exceptions no longer redacted on the way to the agent, and tool descriptions that state when to use each tool and what to call next.\n\nv1.8.3 | 2026-07-20T03:47:52.453Z | user\n\nPer-target username can now come from an env var, resolved per access like the password; documented credential variables corrected against what each repo's code actually reads\n\nv1.8.2 | 2026-07-19T18:06:29.790Z | user\n\nMCP server moved into the package namespace — fixes two skills in one environment silently overwriting each other's server; agent-guardrails.md for local/small models now ships in every skill\n\nv1.8.1 | 2026-07-19T11:28:01.561Z | user\n\nRead-only mode now documented on every surface that teaches it (SKILL.md, setup-guide, capabilities) and reported by doctor\n\nv1.8.0 | 2026-07-19T09:47:29.608Z | user\n\nRead-only mode (11 write tools withheld), list-result envelope, declared environments; autonomy table corrected — run_traceflow is a write, not an L1 auto-run\n\nv1.7.5 | 2026-07-13T07:17:08.550Z | user\n\ndead-code cleanup; family version alignment\n\nv1.7.4 | 2026-07-13T04:52:25.182Z | user\n\nFamily version alignment to 1.7.4 (substantive change this cycle is in vmware-monitor: host-check boundary read batching).\n\nv1.7.3 | 2026-07-03T00:48:45.746Z | user\n\nFamily version alignment (v1.7.3)\n\nv1.7.2 | 2026-07-02T14:31:15.608Z | user\n\nName search beyond 1000 via Policy Search API + list pagination\n\nv1.7.1 | 2026-07-02T10:53:04.760Z | user\n\nFamily version alignment with v1.7.1 (AIops/Monitor large-inventory scale fix, issue #31).\n\nv1.7.0 | 2026-06-27T01:01:40.807Z | user\n\nguided init wizard + form-body auth teaching\n\nv1.6.1 | 2026-06-24T00:01:03.703Z | user\n\nv1.6.1 .env password b64 obfuscation\n\nv1.6.0 | 2026-06-22T09:17:30.287Z | user\n\nv1.6.0 trust architecture: undo tokens + governance harness (budget/audit/risk-tiers)\n\nv1.5.39 | 2026-06-22T00:42:23.487Z | user\n\nv1.5.39: AIops snapshot-delete async + honest timeout (token-burn fix), Storage browse timeout fix; others version-aligned\n\nv1.5.38 | 2026-06-12T06:59:44.655Z | user\n\nbacklog finish: server split\n\nv1.5.37 | 2026-06-12T01:58:24.654Z | user\n\nbacklog: robust group-delete guard, list pagination\n\nv1.5.36 | 2026-06-11T23:21:54.704Z | user\n\nerror translation, tag-remove parity, audit completeness\n\nv1.5.35 | 2026-06-10T00:45:12.122Z | user\n\nSecurity hardening: safe error handling, TLS/path/permission fixes\n\nv1.5.32 | 2026-06-08T02:47:36.593Z | user\n\nv1.5.32: VM tagging/IDPS/Traceflow rewritten to real NSX APIs\n\nv1.5.30 | 2026-06-07T13:23:24.192Z | user\n\nv1.5.30: Glama TDQS tool description quality rewrite\n\nv1.5.29 | 2026-05-29T02:19:56.506Z | user\n\nNSX/VCF version compatibility table added to capabilities reference\n\nv1.5.28 | 2026-05-20T10:00:19.168Z | user\n\nFix subclass() arg 1 must be a class in goose/old-mcp environments. v1.5.25-1.5.27 only addressed PEP 604 X|None -> Optional[X] but kept 'from __future__ import annotations'; under mcp 1.10-1.13 FastMCP's issubclass() on string annotations crashed server load. This release removes the future import. CLAUDE.md pitfall #33 updated.\n\nv1.5.27 | 2026-05-20T06:57:17.212Z | user\n\nLoosen Python requirement to >= 3.10 (was >=3.11). v1.5.25/26 PEP 604 fix already enables 3.10 at runtime; this release lifts pip download/install block.\n\nv1.5.26 | 2026-05-20T06:17:26.262Z | user\n\nMCP server Python 3.10 compatibility (踩坑 #33): PEP 604 X|None → Optional[X] in tool signatures; mcp_cmd Python version guard; mcp[cli]>=1.10\n\nv1.5.23 | 2026-05-19T02:58:31.063Z | user\n\nVCF 9.0 / 9.1 compatibility declared. README version-compat tables updated. Added Official Broadcom References (VCF Python SDK, REST APIs, CLI tools).\n\nv1.5.22 | 2026-05-08T23:25:14.669Z | user\n\nv1.5.22 family alignment for Smithery rollout\n\nv1.5.21 | 2026-05-08T23:20:39.572Z | user\n\nv1.5.21 family alignment + python-multipart 0.0.27\n\nv1.5.20 | 2026-05-08T22:40:01.156Z | user\n\nv1.5.20 family alignment + MCP Registry mcp-name markers\n\nv1.5.19 | 2026-05-06T04:03:23.567Z | user\n\nv1.5.19 — yjs review fixes: NSX CLI subcommand imports (CRITICAL), VKS delete_tkc_cluster ApiClient leak, Harden Twin snapshot_id indexes + LEFT JOIN report, Policy approval gate + singleton lock; py3.11+ requirement; family_smoke recursive subcommand smoke.\n\nv1.5.18 | 2026-05-02T12:11:43.948Z | user\n\nv1.5.18 — family alignment + tooling normalization. Migrated dev deps to [dependency-groups] (PEP 735); added regression eval suite (tests/eval/regression/) catching v1.5.x release blockers.\n\nv1.5.17 | 2026-05-01T11:47:09.673Z | user\n\nv1.5.17 - Family alignment with vmware-pilot v1.5.17 (review_workflow + investigate_alert) and vmware-policy v1.5.17 (L5 pattern matcher). No source changes in this skill.\n\nv1.5.16 | 2026-05-01T03:31:21.141Z | user\n\nv1.5.16 - Enterprise Harness Engineering alignment: 5-level automation taxonomy (L1-L5) in capabilities.md, expert judgment encoded into Common Workflows pre-flight sections, causal-chain investigation protocol shared across aria/monitor/aiops, family version bump.\n\nv1.5.15 | 2026-04-29T18:29:38.891Z | user\n\nv1.5.15: single-command MCP entry point (vmware-nsx-security mcp), verify_ssl default true. Legacy entry point kept for backward compat.\n\nv1.5.14 | 2026-04-21T12:20:50.339Z | user\n\nv1.5.14: code review fixes by @yjs-2026 + Snyk E005 disclaimer\n\nv1.5.12 | 2026-04-17T10:05:33.302Z | user\n\nSecurity & bug fixes from @yjs-2026 code review\n\nArchive index:\n\nArchive v1.13.0: 8 files, 27486 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (9340b), references/capabilities.md (15246b), references/cli-reference.md (6939b), references/setup-guide.md (6433b), skill-card.md (2628b), SKILL.md (21125b), _meta.json (139b)\n\nFile v1.13.0:SKILL.md\n\n---\nname: vmware-nsx-security\ndescription: >\n  Use this skill whenever the user needs to manage VMware NSX security (rebranded VMware vDefend in VCF 9) — distributed firewall (DFW) policies, security groups, microsegmentation, and IDS/IPS.\n  Directly handles: create/manage DFW policies and rules, security groups, VM tags, network traceflow diagnostics, IDPS profiles and status.\n  Always use this skill for \"create firewall rule\", \"set up microsegmentation\", \"add VM to security group\", \"run traceflow\", \"check IDS status\", \"vDefend firewall rule\", or any NSX security / vDefend / DFW task.\n  Do NOT use for NSX networking operations like segments, gateways, NAT, or routing (use vmware-nsx), or VM lifecycle (use vmware-aiops).\n  For load balancing/AVI/AKO use vmware-avi.\ninstaller:\n  kind: uv\n  package: vmware-nsx-security\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-nsx-security\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_NSX_SECURITY_CONFIG\",\"VMWARE_NSX_SECURITY_<TARGET>_PASSWORD\",\"VMWARE_NSX_SECURITY_<TARGET>_USERNAME\",\"VMWARE_AUDIT_APPROVED_BY\"],\"bins\":[\"vmware-policy\"]},\"homepage\":\"https://github.com/vmware-skills/VMware-NSX-Security\",\"emoji\":\"🔒\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  vmware-policy auto-installed as Python dependency (provides @vmware_tool decorator and audit logging). All write operations audited to ~/.vmware/audit.db.\n  Credentials: Each NSX Manager target requires a per-target password env var in ~/.vmware-nsx-security/.env following the pattern VMWARE_NSX_SECURITY_<TARGET_NAME_UPPER>_PASSWORD. Passwords are never logged or echoed.\n  Destructive operations: DFW policy delete checks for active rules, security group delete checks for references. The three MCP delete tools preview by default — without confirm=True they return the blast radius and change nothing, and confirm=True is refused while a blocker remains or a read failed. IDS/IPS config changes require double confirmation. Traceflow is read-only.\n  No webhooks, no outbound network calls, no guest operations. Local only: stdio MCP + NSX Policy API (HTTPS 443).\n  Transitive dependencies: Only vmware-policy (audit/policy). No post-install scripts or background services.\n---\n\n# VMware NSX Security\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"NSX\" are trademarks of Broadcom. Source code is publicly auditable at [github.com/vmware-skills/VMware-NSX-Security](https://github.com/vmware-skills/VMware-NSX-Security) under the MIT license.\n\nVMware NSX DFW microsegmentation and security — 22 MCP tools for distributed firewall, security groups, VM tags, the DFW exclusion list, Traceflow, and IDPS.\n\n> Domain-focused security skill for NSX-T / NSX 4.x Policy API.\n> **Companion skills**: [vmware-nsx](https://github.com/vmware-skills/VMware-NSX) (networking), [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (VM lifecycle), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only monitoring), [vmware-avi](https://github.com/vmware-skills/VMware-AVI) (AVI/ALB/AKO), [vmware-harden](https://github.com/vmware-skills/VMware-Harden) (compliance baselines).\n> | [vmware-pilot](../vmware-pilot/SKILL.md) (workflow orchestration) | [vmware-policy](../vmware-policy/SKILL.md) (audit/policy)\n\n## What This Skill Does\n\n| Category | Tools | Count |\n|----------|-------|:-----:|\n| **DFW Policy** | list, get, create, update, delete, list rules | 6 |\n| **DFW Rules** | create, update, delete, get stats | 4 |\n| **Security Groups** | list, get, create, delete | 4 |\n| **VM Tags** | list VM tags, apply tag, remove tag | 3 |\n| **Traceflow** | run trace, get result | 2 |\n| **IDPS** | list profiles, get status | 2 |\n| **DFW Exclusions** | list excluded members | 1 |\n\n**Total**: 22 tools (11 read-only + 11 write)\n\n## Quick Install\n\n```bash\nuv tool install vmware-nsx-security==1.13.0\nvmware-nsx-security init      # guided setup: writes config + .env (chmod 600, password grep-safe), then verifies\nvmware-nsx-security doctor\n```\n\n## When to Use This Skill\n\n- List, create, or modify DFW security policies and rules\n- Create security groups based on VM tags, IP ranges, or segment membership\n- Apply or list NSX tags on virtual machines\n- Run Traceflow to trace a packet path and diagnose drop reasons\n- Check IDPS profile configuration, signature status, and global IDS settings\n- Implement zero-trust microsegmentation between application tiers\n- Check the DFW exclusion list — which VMs no distributed-firewall rule reaches\n\n**Use companion skills for**:\n- NSX segments, gateways, NAT, routing, IPAM → `vmware-nsx`\n- VM lifecycle, deployment, guest ops → `vmware-aiops`\n- vSphere inventory, health, alarms, events → `vmware-monitor`\n- Storage: iSCSI, vSAN, datastores → `vmware-storage`\n- Tanzu Kubernetes → `vmware-vks`\n- Load balancing, AVI/ALB, AKO, Ingress → `vmware-avi`\n\n## Related Skills — Skill Routing\n\n| User Intent | Recommended Skill |\n|-------------|-------------------|\n| NSX security: DFW rules, security groups, IDS/IPS | **vmware-nsx-security** ← this skill |\n| NSX networking: segments, gateways, NAT, routing | **vmware-nsx** |\n| Read-only vSphere monitoring, alarms, events | **vmware-monitor** |\n| VM lifecycle, deployment, guest ops | **vmware-aiops** |\n| Storage: iSCSI, vSAN, datastores | **vmware-storage** |\n| Tanzu Kubernetes | **vmware-vks** |\n| Multi-step workflows with approval | **vmware-pilot** |\n| Compliance baselines (CIS / 等保 / PCI-DSS), drift detection, LLM remediation advisor | **vmware-harden** (`uv tool install vmware-harden`) |\n| Load balancer, AVI, ALB, AKO, Ingress | **vmware-avi** (`uv tool install vmware-avi`) |\n| Audit log query | **vmware-policy** (`vmware-audit` CLI) |\n\n## Common Workflows\n\n### Implement App-Tier Microsegmentation\n\n**Pre-flight (judgment — DFW changes can lock everyone out)**:\n- **Default-allow first**: the very first rule in any new policy must be ALLOW for management traffic (DNS, NTP, vCenter, SSH from jumphost). Without it, the moment you add a default-deny you blackhole your own access.\n- Tag inventory: confirm the VMs you intend to protect actually carry the tag (`tag list <vm>`). A group based on a non-existent tag matches zero VMs — the policy will appear \"applied\" but enforce nothing.\n- Category choice: `Application` for app-tier microseg (rules evaluated late, after Infrastructure rules pass through). Using `Emergency` for routine rules will starve real incident-response capacity.\n- Stateless? Default to stateful — NSX DFW is stateful and almost no rule should be stateless. Stateless = both directions must be explicitly allowed.\n- Always start with **logging enabled** on new rules; disable later once verified. Silent drops are the worst kind of bug.\n\n**Steps**:\n1. Tag the VMs first (see workflow below) — empty groups = no enforcement\n2. Create groups via the `create_group` MCP tool with `tag_scope`/`tag_value` (the tag condition is matched as `\"scope|tag\"`, e.g. `tier|web`; note multiple criteria types — tag/IP/segment — are ORed, not ANDed)\n3. `policy create app-microseg --category Application`\n4. Add rules in order: ALLOW management → ALLOW intra-tier → ALLOW web→app on app-port → DROP any-any with logging\n5. Verify with traceflow (see below) **before** enabling default-deny\n\n### Answer \"is this VM protected by the DFW?\"\n\nNever from the policy and rule listings alone. A VM on the **DFW exclusion list**\nhas no distributed firewall in its datapath: the rules that name it exist and\nnone of them applies. On a VCF estate the management VMs (vCenter, VCF\nOperations, NSX managers) are commonly excluded — one real 9.1 fabric had 10 of\n12 hosts on that list.\n\n1. `list_dfw_exclusions` — the whole list, resolved to the VMs in each group.\n   Check `scope`: `\"user\"` means system-owned exclusions are **not** in the\n   answer, so an empty list there is not proof of anything.\n2. `list_vm_tags <vm>` — `dfw_excluded` is the per-VM verdict. `true` means no\n   rule reaches it; `null` means the list could not be read, which is **not**\n   `false`, so say \"unknown\" rather than \"protected\".\n3. Only then read `list_dfw_policies` / `list_dfw_rules` for what is enforced on\n   the VMs that are not excluded. That listing carries `exclusion_note` whenever\n   anything is on the list.\n\n### Apply NSX Tags to VMs\n\n**Judgment**: tags drive group membership which drives DFW enforcement. A misspelled tag silently excludes a VM from protection. Always re-list after applying.\n\n1. `tag list my-web-vm-01` → record the VM external ID, also see what tags already exist (avoid duplicates / typo collisions)\n2. `tag apply <vm-external-id> --scope tier --value web`\n3. **Verify**: `tag list my-web-vm-01` again → confirm the new tag is present AND no unexpected ones\n\n### Trace a Packet with Traceflow\n\n**Judgment**: traceflow is your verification mechanism for any DFW change. Run it **before** enabling deny rules and **after** every rule modification. Don't trust \"looks right in the UI.\"\n\n1. Get source VM's logical port ID via `vmware-nsx troubleshoot vm-segment`\n2. `traceflow run <lport-id> --src-ip <src> --dst-ip <dst> --proto TCP --dst-port <port>`\n3. Inspect the DFW hit chain: which rule matched, ALLOW or DROP, and at which transport node\n4. **Common failure**: rule matches at category Application but is shadowed by an earlier DROP at category Environment — read the trace top-to-bottom, not just the final verdict\n\n### Check DFW Policy Hit Counts\n\n```bash\nvmware-nsx-security policy list\nvmware-nsx-security rule list <policy-id>\nvmware-nsx-security rule stats <policy-id> <rule-id>\n```\n\n### Multi-Target Operations\n\nAll commands accept `--target <name>` to operate against a specific NSX Manager:\n\n```bash\n# Default target\nvmware-nsx-security policy list\n\n# Specific target\nvmware-nsx-security policy list --target nsx-prod\nvmware-nsx-security group list --target nsx-lab\n```\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models (Ollama, Qwen) | **CLI** | ~2K tokens vs ~8K for MCP |\n| Cloud models (Claude, GPT-4o) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | Type-safe parameters, structured output |\n\nRunning with local or small models? See [`references/agent-guardrails.md`](references/agent-guardrails.md) for explicit operating rules.\n\n## MCP Tools (22 — 11 read, 11 write)\n\nAll MCP tools accept an optional `target` parameter.\n\n`list_dfw_policies`, `list_dfw_rules`, `list_groups` and `list_idps_profiles` return the family\nlist envelope — `{items, returned, limit, total, truncated, hint}` — rather than a bare array.\nRead the rows from `items` and check `truncated` before concluding a listing is complete; a\n50-row default page looks identical to a whole estate without it. `total` is stated only where\nthe scan proved it: it is the real count on an unfiltered listing that stayed under the\n1000-item `get_all` cap, and `null` for name-filtered listings, capped scans, and\n`list_dfw_rules` (whose fetch is bounded to the requested window). `truncated` says `items` is not the whole\ncollection; it is still true on the last page of a walk, so page with `next_offset` and stop\nwhen it is `null`, never on `truncated`. The `hint` says which of the two you are looking at.\nErrors return\n`{error, hint}` (a dict, not a one-element list).\n\n| Category | Tool | Type | Description |\n|----------|------|:----:|-------------|\n| DFW Exclusions | `list_dfw_exclusions` | Read | List the DFW exclusion list — members no DFW rule reaches. Read this before calling any VM micro-segmented |\n| DFW Policy | `list_dfw_policies` | Read | List all DFW security policies with category, sequence, and rule count |\n| | `get_dfw_policy` | Read | Get policy details: category, stateful, locked, scope, tags |\n| | `create_dfw_policy` | Write | Create a new DFW policy with category and sequence number |\n| | `update_dfw_policy` | Write | Partial update: display_name, description, sequence_number, stateful |\n| | `delete_dfw_policy` | Write | Delete policy — previews unless `confirm=True`; refuses if active rules exist |\n| | `list_dfw_rules` | Read | List rules in a policy: action, sources, destinations, services |\n| DFW Rules | `create_dfw_rule` | Write | Create rule with sources/destinations/services/action/scope |\n| | `update_dfw_rule` | Write | Partial update rule fields |\n| | `delete_dfw_rule` | Write | Delete a rule from a policy — previews unless `confirm=True` |\n| | `get_dfw_rule_stats` | Read | Get packet/byte/session/hit counts and popularity_index for a rule |\n| Security Groups | `list_groups` | Read | List all security groups with expression count |\n| | `get_group` | Read | Get group details: expression criteria + up to 50 effective VM members |\n| | `create_group` | Write | Create group with tag/IP/segment membership criteria (tag matched as \"scope\\|tag\"; multiple criteria ORed) |\n| | `delete_group` | Write | Delete group — previews unless `confirm=True`; refuses if referenced by rules/scopes or a parent group, or if the scan fails |\n| VM Tags | `list_vm_tags` | Read | List NSX tags on a VM by display name |\n| | `apply_vm_tag` | Write | Apply a scope/value tag to a VM (additive, preserves existing tags) |\n| | `remove_vm_tag` | Write | Remove a scope/value tag from a VM (other tags preserved; may change dynamic group membership) |\n| Traceflow | `run_traceflow` | Write | Inject probe packet; returns operation_state + hop-by-hop observations (by resource_type) + dfw_hits |\n| | `get_traceflow_result` | Read | Check operation_state/observations of an existing traceflow |\n| IDPS | `list_idps_profiles` | Read | List IDPS profiles with severity and filter criteria |\n| | `get_idps_status` | Read | Get IDPS signature status + global IDS settings (auto_update, syslog export) |\n\nThe three `delete_*` tools preview by default: without `confirm=True` they return `blast_radius` — the object, what it holds or matches (a policy's `rule_count`, a rule's action, sources, destinations and services, a group's `references`), `blockers` and `unmeasured` — and delete nothing. Show it to the user and pass `confirm=True` only after they decide; it is refused while a blocker remains or a read failed.\n\n## CLI Quick Reference\n\n```bash\n# DFW Policy\nvmware-nsx-security policy list [--target <name>]\nvmware-nsx-security policy get <policy-id>\nvmware-nsx-security policy create <id> --name \"Display Name\" --category Application [--dry-run]\nvmware-nsx-security policy delete <id> [--dry-run]\n\n# DFW Rules\nvmware-nsx-security rule list <policy-id>\nvmware-nsx-security rule stats <policy-id> <rule-id>\nvmware-nsx-security rule delete <policy-id> <rule-id> [--dry-run]\n\n# Security Groups\nvmware-nsx-security group list\nvmware-nsx-security group get <group-id>\nvmware-nsx-security group delete <group-id> [--dry-run]\n\n# Tags\nvmware-nsx-security tag list <vm-display-name>\nvmware-nsx-security tag apply <vm-external-id> --scope env --value production [--dry-run]\nvmware-nsx-security tag remove <vm-external-id> --scope env --value production [--dry-run]\n\n# Traceflow\nvmware-nsx-security traceflow run <lport-id> --src-ip &lt;src-ip&gt; --dst-ip &lt;dst-ip&gt;\n\n# IDPS\nvmware-nsx-security idps profiles\nvmware-nsx-security idps status\n\n# Diagnostics\nvmware-nsx-security doctor [--skip-auth]\n```\n\n## Troubleshooting\n\n### \"Cannot delete policy — active rules exist\"\n\n`delete_dfw_policy` checks for active rules before deleting. Use `vmware-nsx-security rule list <policy-id>` to see which rules need to be removed first. Then delete each rule individually before retrying the policy deletion.\n\n### \"Cannot delete group — referenced by DFW rules\"\n\n`delete_group` scans DFW and gateway policies for the group in rule source_groups, destination_groups and applied-to scope, plus policy-level scope, and checks parent groups. Remove the group from those references first (via `update_dfw_rule` replacing the group path with 'ANY' or another group), then retry. If the error says the reference scan itself failed, deletion was aborted as a precaution — verify NSX connectivity with `vmware-nsx-security doctor` and retry.\n\n### \"No virtual machine named ... exists in the NSX fabric inventory\"\n\n`list_vm_tags` looks up VMs by display name via the NSX fabric API. Common causes:\n1. Display name mismatch — the name in NSX Manager may differ from vCenter. Check `vmware-monitor vm list` for the exact NSX fabric display name.\n2. VM not registered — newly deployed VMs may take a minute to appear in the NSX fabric.\n3. Multiple VMs with the same name — use `apply_vm_tag` with the specific external_id.\n\n### Traceflow returns empty observations\n\n1. If `operation_state` is `IN_PROGRESS`, the trace has not finished — poll again with `get_traceflow_result <traceflow-id>`.\n2. Verify the `src_lport_id` is the correct logical port attachment UUID — not the segment port path. Get it from `vmware-nsx troubleshoot vm-segment <vm>`.\n3. The source VM must be powered on and connected to an NSX overlay segment.\n4. If the VM is on a VLAN-backed segment, Traceflow is not supported.\n5. NSX Manager requires the transport node hosting the source VM to be reachable. Check `vmware-nsx health transport-nodes`.\n\n### DFW rule stats show zero hits\n\nA newly created rule will have zero hit counts until traffic matches it. If expected traffic still shows zero:\n1. Confirm the rule is not disabled (`disabled: false` in `list_dfw_rules` output).\n2. Check that source/destination group membership is correct using `get_group`.\n3. Verify rule sequence number — a lower-sequence rule with ALLOW/DROP may be matching first.\n\n### \"Password not found\" error\n\nPassword variable convention: `VMWARE_NSX_SECURITY_<TARGET_UPPER>_PASSWORD`\nwhere hyphens are replaced by underscores. For target `nsx-prod`:\n`VMWARE_NSX_SECURITY_NSX_PROD_PASSWORD`. Check `~/.vmware-nsx-security/.env`.\n\n### `invalid peer certificate: UnknownIssuer` (uvx)\n\nCorporate TLS proxy not trusted by uv's bundled cert store. Use the v1.5.15+\nsingle-command form `vmware-nsx-security mcp` (no PyPI re-resolve), or\n`export UV_NATIVE_TLS=true` to make uv use the system cert store.\n\n## Safety\n\n- **Audit logging**: All write operations logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy) with timestamp, user, target, operation, parameters, and result\n- **Dependency checks**: `delete_dfw_policy` checks for active rules; `delete_group` checks for DFW rule references — prevents accidental cascade failures\n- **MCP delete preview**: the three MCP delete tools act only with `confirm=True`; a bare call returns the blast radius and deletes nothing\n- **Input validation**: All IDs validated against safe character set (alphanumerics, hyphens, underscores, dots); all text fields sanitized to strip control characters\n- **Dry-run mode**: CLI write commands support `--dry-run` to preview API calls without executing\n- **Double confirmation**: CLI destructive operations (delete) require two separate confirmation prompts\n- **Credential safety**: Passwords loaded only from environment variables (`.env` file), never from `config.yaml`\n- **No networking changes**: Cannot modify segments, gateways, NAT, or routing — that scope belongs to `vmware-nsx`\n- **Prompt injection defense**: All API-sourced strings passed through `_sanitize()` before inclusion in tool output\n\n## Setup\n\n```bash\nuv tool install vmware-nsx-security==1.13.0\nmkdir -p ~/.vmware-nsx-security\ncp config.example.yaml ~/.vmware-nsx-security/config.yaml\n# Edit config.yaml with your NSX Manager targets\n\n# Add to ~/.vmware-nsx-security/.env (create if missing, chmod 600):\n# VMWARE_NSX_SECURITY_NSX_PROD_PASSWORD=<your-password>\nchmod 600 ~/.vmware-nsx-security/.env\n\nvmware-nsx-security doctor\n```\n\n> All tools are automatically audited via vmware-policy. Audit logs: `vmware-audit log --last 20`\n\n> Full setup guide: see `references/setup-guide.md`\n\n## Architecture\n\n```\nUser (natural language)\n  |\nAI Agent (Claude Code / Goose / Cursor)\n  | reads SKILL.md\nvmware-nsx-security CLI or MCP server (stdio transport)\n  | NSX Policy API (REST/JSON over HTTPS)\nNSX Manager\n  |\nDFW Policies / Rules / Security Groups / Tags / IDPS\n```\n\nThe MCP server uses stdio transport (local only, no network listener). All connections to NSX Manager use HTTPS on port 443.\n\n## Audit & Safety\n\nAll operations are automatically audited via vmware-policy (`@vmware_tool` decorator):\n- Every tool call logged to `~/.vmware/audit.db` (SQLite, framework-agnostic)\n- Policy rules enforced via `~/.vmware/rules.yaml` (deny rules, maintenance windows, risk levels)\n- Risk classification: each tool tagged as low/medium/high/critical\n- View recent operations: `vmware-audit log --last 20`\n- View denied operations: `vmware-audit log --status denied`\n\nvmware-policy is automatically installed as a dependency — no manual setup needed.\n\n## License\n\nMIT — [github.com/vmware-skills/VMware-NSX-Security](https://github.com/vmware-skills/VMware-NSX-Security)\n\nFile v1.13.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-nsx-security\",\n  \"version\": \"1.13.0\",\n  \"publishedAt\": 1789915933991\n}\n\nFile v1.13.0:references/agent-guardrails.md\n\n# Operating vmware-nsx-security with a local / small model\n\nClaude-class models drive this skill without special instruction. Smaller and\nlocally-hosted models — Llama 3.3 70B, Qwen, Mistral, and similar, served\nthrough Goose, Ollama, or OpenShift AI — need explicit operating rules to call\ntools reliably.\n\nThis page exists because an operator wrote those rules by hand first. The\nguardrails below are adapted, with thanks, from the working configuration\n[@juanpf-ha](https://github.com/juanpf-ha) developed while running\nvmware-monitor and vmware-aria against a production vSphere estate with Llama\n3.3 70B FP8 on an on-prem H100\n([VMware-AIops#31](https://github.com/vmware-skills/VMware-AIops/issues/31)). The\ncross-skill rules are identical across this family; the parts below marked\nvmware-nsx-security are specific to this skill.\n\nvmware-nsx-security exposes 22 MCP tools, 11 of which change state. This is a\nfirewall: a wrong rule does not raise an error, it silently permits or blocks\ntraffic, and nobody finds out until something breaks or nothing does.\n\n> **Disclaimer**: This is a community-maintained open-source project and is\n> **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom\n> Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom.\n\n---\n\n## First: the rules you no longer need to write\n\nSeveral guardrails from the original configuration are now enforced by the\nskill itself. Prompt instructions are advisory — a model can ignore them.\nThese are structural, so it cannot.\n\n| Guardrail you would otherwise prompt for | Now enforced by |\n|---|---|\n| \"Check whether a group is used anywhere before deleting it\" | **`delete_group` scans** DFW and gateway-firewall rule sources, destinations, applied-to scope and policy scope, plus parent groups, and refuses when referenced. It also refuses when the scan itself fails, rather than assuming the group is unused. |\n| \"Do not delete a policy that still has rules in it\" | **`delete_dfw_policy` refuses** while active rules exist. |\n| \"Show me what a delete would remove before it happens\" | **The three delete tools preview by default.** Without `confirm=True` they return `blast_radius` and delete nothing; `confirm=True` is refused while a blocker remains or a read failed. Pass it only after the user has seen the preview. |\n| \"Use explicit limits for queries that may return large amounts of data\" | **The list envelope.** `list_dfw_policies`, `list_dfw_rules`, `list_groups` and `list_idps_profiles` return `{items, returned, limit, total, truncated, hint}`, so the model reads truncation instead of guessing at it. A 50-row default page and a whole estate look identical without it. |\n| \"If a listing came back empty, say so rather than claiming the call failed\" | Same envelope. Empty `items` with `truncated: false` means checked-and-none — a stated result, not a silence the model has to interpret. Note `total` is `null` for name-filtered and capped listings; `truncated: true` means `items` is not the whole collection and stays true on the last page, so page with `next_offset` and stop when it is `null`. |\n| \"Log every state change you make\" | **The `@vmware_tool` decorator.** Every write is recorded to `~/.vmware/audit.db` before the model sees the result, and policy rules are evaluated ahead of execution. |\n| \"Block state-changing writes against a production target\" | **Policy.** An opt-in environment-scoped `deny` rule in `~/.vmware/rules.yaml` matches a target's `environment:` label and refuses matching writes before execution. |\n\n---\n\n## The system prompt\n\nEverything below still benefits from being stated explicitly. Copy this into\nyour agent's instruction block.\n\n```text\n## Tool use\n\n- Always call an MCP tool before answering any question about the current NSX\n  environment. Never answer from memory or assumption.\n- Never describe a tool call, and never output a JSON example, instead of\n  executing the tool. If you intend to call a tool, call it.\n- If a tool fails, report the actual error text. Do not complete the answer\n  with assumptions about what the result would have been.\n- Use explicit limits on queries that may return large amounts of data. Do not\n  request unlimited results unless the user asks for them.\n- Every tool accepts an optional target. When more than one NSX Manager is\n  configured, name the target explicitly rather than relying on the default.\n\n## Skill routing\n\n- vmware-nsx-security: DFW policies and rules, security groups, VM tags,\n  IDS/IPS profiles and status, Traceflow.\n- vmware-nsx: segments, Tier-0 and Tier-1 gateways, BGP, NAT, static routes,\n  IP pools, transport nodes. Routing and switching are not this skill.\n- vmware-monitor: read-only vCenter inventory, hosts, alarms, events.\n- vmware-aiops: VM lifecycle.\n- vmware-harden: compliance baselines and drift, including firewall posture.\n- vmware-pilot: multi-step workflows that need approval gates.\n\n## Data fidelity\n\n- Never invent policies, rules, groups, tags, IP addresses or services. If a\n  tool did not return it, it does not exist for this answer.\n- Preserve the exact action, direction, disabled flag, category and sequence\n  values the tools return. Do not translate, normalise, or prettify enum\n  values, and never render ALLOW as \"allowed\" or DROP as \"blocked\".\n- Report every rule field the user asked for, in the order returned. Rule\n  evaluation is order-dependent, so a reordered list is a wrong answer.\n- If a requested field was not returned, show it as \"not available\". Do not\n  infer it from other fields.\n- When a response is long, report every item it contains. If a result is\n  truncated, the tool says so explicitly — report the truncation rather than\n  describing the visible subset as the whole.\n\n## Analysis discipline\n\n- Separate observed data from interpretation. State which is which.\n- Do not claim a security exposure unless the tool output contains explicit\n  supporting evidence. An absent rule is not proof traffic is permitted; a\n  zero hit count is not proof a rule is unused.\n- Avoid generic recommendations that are not directly supported by the results.\n- Never state that a change \"will not affect existing traffic\". You cannot\n  know that from the tool output.\n\n## Writes in vmware-nsx-security\n\n- run_traceflow is a write: it injects a probe packet. Do not call it to\n  \"just check\" something.\n- Sequence number decides which rule matches first. State the sequence you are\n  proposing and what it will sit before and after.\n- Tag membership is matched as \"scope|tag\", and multiple criteria are ORed.\n  Read get_group before assuming what a group contains.\n- remove_vm_tag can change dynamic group membership, and therefore which rules\n  apply to a VM. Say so before proposing it.\n- get_group returns at most 50 effective members. member_count is the group's\n  real size, and members.truncated says whether the sample withheld any — read\n  those two rather than counting members.items.\n```\n\n---\n\n## Known failure modes on small models\n\nObserved with Llama 3.3 70B FP8 (Goose, on-prem H100), and useful as a\nchecklist when evaluating any local model against these skills:\n\n| Symptom | Mitigation |\n|---|---|\n| Describes a tool call, or emits a JSON example, instead of executing it | The \"never describe a tool call\" rule above. Also check your harness is not echoing tool schemas into context — models imitate the nearest format they see. |\n| Long tool responses: omits items, or reports \"no data returned\" when data was present | Ask for explicit limits so responses stay small. Check the envelope's `truncated` / `returned` / `total` fields rather than trusting the model's summary — a \"no data\" claim is checkable against `returned`. A dropped rule in a firewall listing is a security answer that is quietly wrong. |\n| Adds generic recommendations unsupported by results | The \"analysis discipline\" rules. Firewall output attracts invented advice (\"consider tightening this rule\") more than anything else in the family. |\n| Drops requested fields or reorders results | State the required fields and ordering in the request itself. Rule order is semantic here, not cosmetic. |\n| Multi-tool workflows take 30–50s end to end | `get_dfw_policy` and `get_group` each answer a whole question in one call. Fetch the policy once and read its rules from that result rather than looping. |\n| Calls `run_traceflow` believing it to be a read | The rule above. Its name suggests a query; its effect is an injected packet. |\n| Reads a zero hit count as \"this rule is unused\" and proposes deleting it | The \"zero hit count is not proof\" rule. A new rule has zero hits by construction. |\n| Summarises ALLOW/DROP into prose and inverts the meaning | The \"never render ALLOW as allowed\" rule. Keep the enum verbatim. |\n| Retries a refused deletion, or works around it by deleting the references first | The refusals are guards. Report the reason and let a human decide. |\n\n## Reporting results\n\nLocal-model compatibility is an explicit design constraint for this family, and\nthe evidence base is small. If you evaluate a model against this skill —\nQwen, Mistral, Granite, or anything else — a report of what worked and what did\nnot is genuinely useful:\n[github.com/vmware-skills/VMware-NSX-Security/issues](https://github.com/vmware-skills/VMware-NSX-Security/issues).\n\nFile v1.13.0:references/capabilities.md\n\n# VMware NSX Security — Capabilities Reference\n\n## Automation Level Reference\n\nEach operation is classified by autonomy level per the Enterprise Harness Engineering framework:\n\n| Level | Meaning | Agent autonomy | Examples in this skill |\n|:-:|---|---|---|\n| **L1** | Read-only, raw data | Always auto-run | `list_dfw_policies`, `get_dfw_policy`, `list_dfw_rules`, `get_dfw_rule_stats`, `list_groups`, `get_group`, `list_vm_tags`, `get_traceflow_result`, `list_idps_profiles`, `get_idps_status` |\n| **L2** | Read + analysis / recommendation | Always auto-run | DFW rule conflict detection, shadowed-rule analysis, security group reference graph, traceflow path interpretation |\n| **L3** | Single write — user must approve | Only after explicit confirmation; destructive CLI ops require double-confirm + `--dry-run`; the three MCP deletes preview by default and act only with `confirm=True` | `create_dfw_policy`, `create_dfw_rule`, `delete_dfw_rule`, `create_group`, `delete_group`, `apply_vm_tag`/`remove_vm_tag`, `run_traceflow` (injects a synthetic packet) |\n| **L4** | Multi-step plan / apply workflow | Plan generation auto; apply gated by user approval | *(roadmap — staged microsegmentation rollouts, emergency-block playbooks)* |\n| **L5** | Auto-remediation from learned pattern | Pattern library only; requires `risk:low` + `reversible:true` + `repeatable:true` | *(roadmap — candidates: orphaned-SG cleanup, expired temp-block rule removal)* |\n\n**Notes**:\n- L1/L2 tools are always safe for agents to call without confirmation.\n- **List envelope**: `list_dfw_policies`, `list_dfw_rules`, `list_groups` and `list_idps_profiles` return `{items, returned, limit, total, truncated, hint}` instead of a bare array, so an agent can tell a complete answer from a first page rather than inferring it (VMware-AIops issue #31). `total` is reported only where the scan proved it — the real count on an unfiltered listing under the 1000-item `get_all` cap; `null` for name-filtered listings (the Search API returns matches, not a countable set), for scans that stopped at the cap, and for `list_dfw_rules` (bounded to `offset + limit` by design). Page with the `next_offset` extra — pass it back as `offset` and stop when it is `null`. Never loop on `truncated`: it answers \"is `items` the whole collection?\", which is still `true` on the last page of a walk. The `hint` distinguishes them — mid-walk it names the next offset; on the last page it says there is no next page; past the end it says so and points back to offset 0. It never advises raising a limit that cannot return another row.\n- **`rule_count` on `list_dfw_policies`**: an int where NSX reported one, `null` where it did not — `null` means \"not retrieved\", never \"no rules\". The unfiltered listing asks for the count via `include_rule_count` (NSX omits the field otherwise); a name-filtered listing is resolved through the Policy Search API, which carries no rule counts, so every count there reads `null`. Any `null` adds a `rule_count_note` to the envelope. To find out what a `null` policy enforces, call `list_dfw_rules` on it — never read `null` as an empty policy.\n- L3 tools always pass through the `@vmware_tool` decorator: connection check → policy check → audit log → double-confirm. DFW policy delete additionally checks for active rules; SG delete checks for references.\n- **MCP deletes preview by default** (`delete_dfw_policy`, `delete_dfw_rule`, `delete_group`). A call without `confirm=True` reads what the delete would remove and returns `{\"action\": \"preview\", \"blast_radius\": {...}}`, deleting nothing. `blast_radius` names the object and what it measured — a policy's category, `rule_count` and `rule_ids`; a rule's parent policy, action, sources, destinations, services, scope and direction; a group's `expression_count`, `reference_count` and `references` — plus `blockers` and `unmeasured`. `confirm=True` re-measures and is refused, deleting nothing, while a blocker remains (rules left in the policy, entities referencing the group) or while any of those reads failed; the refusal is `{\"error\", \"hint\", \"blast_radius\"}`. Show the preview to the user; set `confirm=True` only after they decide — not because they asked for the delete before seeing it. The preview is logged to the skill audit log as `preview`, not `ok`.\n- For Segment/Gateway/NAT (network plane) see [vmware-nsx](https://github.com/vmware-skills/VMware-NSX).\n\n## DFW Policy Categories\n\nNSX DFW policies are evaluated in category order (lower category = higher priority):\n\n| Category | Priority | Typical Use |\n|----------|:--------:|-------------|\n| Ethernet | 1 | Layer-2 rules (MAC-based) |\n| Emergency | 2 | Incident response — block specific IPs or VMs immediately |\n| Infrastructure | 3 | DNS, NTP, vCenter management traffic |\n| Environment | 4 | Cross-environment rules (e.g. prod → lab) |\n| Application | 5 | Application-tier microsegmentation (most common) |\n\n`create_dfw_policy` validates the category and rejects anything outside this set.\n\n## DFW Rule Actions\n\n| Action | Behaviour |\n|--------|-----------|\n| ALLOW | Permit the traffic |\n| DROP | Silently discard the packet (no RST/ICMP) |\n| REJECT | Discard + send TCP RST or ICMP unreachable |\n| JUMP_TO_APPLICATION | Skip to Application category rules — only valid in policies whose category is Environment |\n\n## DFW Rule Statistics Fields\n\n`get_dfw_rule_stats` aggregates the per-enforcement-point `RuleStatistics`\narray: `packet_count`, `byte_count`, `session_count`, `hit_count` (summed)\nand `popularity_index` (max). There is no `population_count` field in the\nNSX API.\n\n## Security Group Expression Types\n\nGroups support three membership condition types:\n\n| Type | Parameter | Example |\n|------|-----------|---------|\n| Tag Condition | `tag_scope` + `tag_value` | scope=tier, value=web |\n| IP Address | `ip_addresses` | ['10.0.1.0/24', '10.0.2.5'] |\n| Segment Path | `segment_paths` | ['/infra/segments/web-seg'] |\n\nThe tag Condition is sent as a Policy `Condition` with a pipe-delimited\n`value` of `\"scope|tag\"` (e.g. `tier|web`; tag-only matching uses `\"|tag\"`).\n\nMultiple criteria in one group are **ORed** (VM matches ANY condition):\nNSX only permits AND between Conditions of the same member type, so\nheterogeneous expression types (Condition vs IPAddressExpression vs\nPathExpression) must join with OR.\n\n## Traceflow Packet Types\n\nThe probe is a `FieldsPacketData` with nested `ip_header` (src_ip, dst_ip,\nttl, protocol number) and `transport_header`; `transport_type` is the L2\ndelivery mode (`UNICAST`), not the protocol.\n\n| Protocol | transport_header | Notes |\n|----------|------------------|-------|\n| TCP | `tcp_header` (src_port, dst_port) | SYN flag set automatically |\n| UDP | `udp_header` (src_port, dst_port) | |\n| ICMP | `icmp_echo_request_header` | Echo request |\n\nCompletion is polled via `operation_state`: `IN_PROGRESS` → `FINISHED`\nor `FAILED`.\n\n## Traceflow Observation Types\n\nObservations are discriminated by `resource_type`:\n\n| resource_type | Meaning |\n|---------------|---------|\n| TraceflowObservationForwarded | Packet forwarded to next hop |\n| TraceflowObservationDropped / TraceflowObservationDroppedLogical | Packet dropped at this component (carries `reason` + `acl_rule_id`) |\n| TraceflowObservationDelivered | Packet delivered to destination |\n| TraceflowObservationReceived | Packet received at a component |\n\nAny observation carrying an `acl_rule_id` (forwarded or dropped by a DFW\nrule) is also summarised in the `dfw_hits` list of the result.\n\n## IDPS Status Output\n\n`get_idps_status` reads two Policy API resources and returns:\n\n- `signature_status` — scalar fields of the signature bundle status\n  resource (e.g. version / update state; exact field names vary by NSX\n  release, so scalars are passed through as-is)\n- `settings` — `auto_update` (automatic signature updates) and\n  `ids_events_to_syslog` from the global IdsSettings resource\n\nIDPS profile `criteria` are polymorphic `filter_name`/`filter_value`\npairs (ATTACK_TYPE, ATTACK_TARGET, CVSS, PRODUCT_AFFECTED); conjunction\nentries between them are always AND and are omitted from parsed output.\n\n## IDPS Severity Levels\n\nNSX IDPS signatures are classified by severity:\n\n| Level | Score Range | Description |\n|-------|-------------|-------------|\n| CRITICAL | 9.0–10.0 | Immediate exploitation, remote code execution |\n| HIGH | 7.0–8.9 | Significant risk, exploitable vulnerabilities |\n| MEDIUM | 4.0–6.9 | Moderate risk, requires specific conditions |\n| LOW | 0.1–3.9 | Informational, denial-of-service potential |\n\n## NSX Tag Conventions\n\nBest practice for NSX tag design:\n\n| Scope | Example Values | Used For |\n|-------|---------------|----------|\n| `tier` | web, app, db | Application tier microsegmentation |\n| `env` | prod, staging, dev | Environment separation |\n| `owner` | team-a, finance | Policy ownership |\n| `compliance` | pci, hipaa | Regulatory scope |\n\n## API Endpoints Reference\n\n| Operation | Method | Path |\n|-----------|--------|------|\n| List policies | GET | /policy/api/v1/infra/domains/default/security-policies |\n| Get policy | GET | /policy/api/v1/infra/domains/default/security-policies/{id} |\n| Create/replace policy | PUT | /policy/api/v1/infra/domains/default/security-policies/{id} |\n| Update policy | PATCH | /policy/api/v1/infra/domains/default/security-policies/{id} |\n| Delete policy | DELETE | /policy/api/v1/infra/domains/default/security-policies/{id} (MCP first GETs the policy and walks its `/rules`) |\n| List rules | GET | /policy/api/v1/infra/domains/default/security-policies/{id}/rules |\n| Create/replace rule | PUT | .../rules/{rule-id} |\n| Update rule | PATCH | .../rules/{rule-id} |\n| Delete rule | DELETE | .../rules/{rule-id} (MCP first GETs the policy and walks its `/rules` for the rule) |\n| Rule statistics | GET | .../rules/{rule-id}/statistics |\n| List groups | GET | /policy/api/v1/infra/domains/default/groups |\n| Get group | GET | /policy/api/v1/infra/domains/default/groups/{id} |\n| Create/replace group | PUT | /policy/api/v1/infra/domains/default/groups/{id} |\n| Delete group | DELETE | /policy/api/v1/infra/domains/default/groups/{id} (first GETs `/policy/api/v1/infra/group-associations?intent_path=<group path>` for parent groups, and walks `security-policies` and `gateway-policies` with their `rules` for references; MCP also GETs the group) |\n| Group members (VMs) | GET | /policy/api/v1/infra/domains/default/groups/{id}/members/virtual-machines |\n| List VM tags | GET | /api/v1/fabric/virtual-machines?display_name={name} |\n| Apply tag | POST | /api/v1/fabric/virtual-machines?action=add_tags |\n| Remove tag | POST | /api/v1/fabric/virtual-machines?action=remove_tags |\n| Create traceflow | POST | /api/v1/traceflows |\n| Get traceflow | GET | /api/v1/traceflows/{id} |\n| Traceflow observations | GET | /api/v1/traceflows/{id}/observations |\n| Delete traceflow | DELETE | /api/v1/traceflows/{id} |\n| IDPS profiles | GET | /policy/api/v1/infra/settings/firewall/security/intrusion-services/profiles |\n| IDPS signature status | GET | /policy/api/v1/infra/settings/firewall/security/intrusion-services/signatures/status |\n| IDPS settings | GET | /policy/api/v1/infra/settings/firewall/security/intrusion-services |\n| DFW exclusion list | GET | /policy/api/v1/infra/settings/firewall/security/exclude-list?system_owned=true |\n\n## DFW Exclusion List\n\nA member on the NSX distributed-firewall exclusion list has **no DFW in its\ndatapath**. Rules that name it, groups that contain it and policies scoped to it\nall still exist, and none of them applies. Any statement that such a VM is\nmicro-segmented is wrong — and wrong in the direction that closes an\ninvestigation rather than opening one. On one real NSX 9.1.0.0200 fabric, 10 of\n12 VMs were on the list, vCenter and VCF Operations and an NSX manager among\nthem.\n\n`list_dfw_exclusions` reads it. Three contract details, checked against the\npublished NSX 9.1.0 API reference rather than recalled:\n\n- **`members` is an array of Group paths, not VM references.** The\n  `PolicyExcludeList` schema types it as strings (max 100). Naming the VMs\n  therefore means resolving each group's\n  `/members/virtual-machines`, which is what the tool does.\n- **`?system_owned=true` is required to see NSX's own exclusions.** Without it\n  only user-added members come back. The response's `scope` says which list\n  answered — `\"user\"` means system exclusions are absent, so an empty result\n  there proves nothing.\n- **The Manager API `GET /api/v1/firewall/excludelist` is removed in NSX 9.1.**\n  Its members *are* VM references, so it is the endpoint one reaches for first;\n  it appears on the 9.1.0 Removed Methods page and would 404. A regression test\n  fails if it ever appears in this package.\n\nThere is no single call for effective per-VM exclusion state\n(`?action=filter` answers one object per request, which is the per-item pattern\n踩坑 #31 forbids). The cost is therefore one GET plus one member fetch per\n*excluded group* — bounded by the exclusion list, never by the estate.\n\nWhere it surfaces:\n\n| Tool | Field | Meaning |\n|------|-------|---------|\n| `list_dfw_exclusions` | `items[]`, `scope` | The list itself, resolved to VMs |\n| `list_vm_tags` | `dfw_excluded`, `dfw_exclusion_note` | Per-VM verdict: `true` / `false` / `null` for \"could not be read\" |\n| `get_group` | `dfw_excluded` (group and each member) | Whether rules naming this group reach it |\n| `list_dfw_policies` | `exclusion_note` | Present only when something is excluded |\n\n`null` is never `false`. A lookup that failed and answered \"not excluded\" would\nbe the same confidently wrong answer about protection, arriving by a different\nroute.\n\n## NSX Version Compatibility\n\n| NSX Version | Support Level | Notes |\n|-------------|--------------|-------|\n| NSX 9.1 | Full | DFW Policy API paths unchanged. VDS 7.0+ required (N-VDS removed in NSX 9 — no impact on DFW skill). |\n| NSX 9.0 | Full | DFW Policy API paths unchanged. Bare-metal NSX agent removed (no impact on DFW skill — Policy API only). |\n| NSX 4.2.x | Full | Latest, all DFW + Security Group + Traceflow + IDS/IPS features supported |\n| NSX 4.1.x | Full | All features supported |\n| NSX 4.0.x | Full | Policy API v1 fully available |\n| NSX-T 3.2.x | Full | Policy API mature, all features work |\n| NSX-T 3.1.x | Full | DFW Policy API stable |\n| NSX-T 3.0.x | Compatible | Policy API available; some IDS/IPS endpoints introduced later |\n| NSX-T 2.5.x | Limited | Policy API available but incomplete; some tools may fail |\n| NSX-V (6.x) | Not supported | Completely different API (SOAP-based). Use legacy tools |\n\n### VCF (VMware Cloud Foundation) Compatibility\n\n| VCF Version | Bundled NSX | Support |\n|-------------|-------------|---------|\n| VCF 9.1 | NSX 9.1 | Full |\n| VCF 9.0 | NSX 9.0 | Full |\n| VCF 5.2 | NSX 4.2.x | Full |\n| VCF 5.1 | NSX 4.1.x | Full |\n| VCF 5.0 | NSX 4.0.x | Full |\n| VCF 4.5 | NSX-T 3.2.x | Full |\n| VCF 4.4 | NSX-T 3.2.x | Full |\n| VCF 4.3 | NSX-T 3.1.x | Full |\n\n**Note**: This skill uses the NSX-T Policy API only. NSX 9 changes that affect the network plane (N-VDS removal, bare-metal agent removal) do not affect DFW, Security Group, Traceflow, or IDS/IPS operations exposed by this skill.\n\nFile v1.13.0:references/cli-reference.md\n\n# VMware NSX Security CLI Reference\n\n## Global Options\n\n| Option | Short | Description |\n|--------|-------|-------------|\n| `--target` | `-t` | NSX Manager target name from config (uses `default_target` if omitted) |\n| `--config` | `-c` | Path to config file (overrides `VMWARE_NSX_SECURITY_CONFIG` env var) |\n| `--dry-run` | | Preview API call without executing (write commands only) |\n| `--help` | | Show help for any command |\n\n---\n\n## `policy` — DFW Policy Management\n\n### `policy list`\nList all DFW security policies.\n\n```bash\nvmware-nsx-security policy list [--target <name>]\n```\n\nOutput columns: ID, Display Name, Category, Seq#, Stateful, Rules\n\n### `policy get`\nGet full details of a DFW policy.\n\n```bash\nvmware-nsx-security policy get <policy-id> [--target <name>]\n```\n\n### `policy create`\nCreate a new DFW security policy.\n\n```bash\nvmware-nsx-security policy create <policy-id> \\\n  --name \"Display Name\" \\\n  [--category Ethernet|Emergency|Infrastructure|Environment|Application] \\\n  [--seq <number>] \\\n  [--description \"text\"] \\\n  [--dry-run] \\\n  [--target <name>]\n```\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `--name` | required | Human-readable policy name |\n| `--category` | Application | Policy evaluation category (validated; Ethernet evaluated first, Application last) |\n| `--seq` | 10 | Sequence number (lower = higher priority) |\n| `--description` | \"\" | Optional description |\n\n### `policy delete`\nDelete a DFW policy (requires no active rules).\n\n```bash\nvmware-nsx-security policy delete <policy-id> [--dry-run] [--target <name>]\n```\n\nPrompts for double confirmation. Fails if the policy contains rules.\n\n---\n\n## `rule` — DFW Rule Management\n\n### `rule list`\nList all rules in a policy.\n\n```bash\nvmware-nsx-security rule list <policy-id> [--target <name>]\n```\n\nOutput columns: ID, Display Name, Action, Direction, Disabled, Logged\n\n### `rule stats`\nGet packet/byte hit-count statistics for a rule.\n\n```bash\nvmware-nsx-security rule stats <policy-id> <rule-id> [--target <name>]\n```\n\nOutput fields: `packet_count`, `byte_count`, `session_count`, `hit_count`\n(summed across enforcement points), `popularity_index` (max).\n\n### `rule delete`\nDelete a DFW rule.\n\n```bash\nvmware-nsx-security rule delete <policy-id> <rule-id> [--dry-run] [--target <name>]\n```\n\nPrompts for double confirmation.\n\n---\n\n## `group` — Security Group Management\n\n### `group list`\nList all security groups.\n\n```bash\nvmware-nsx-security group list [--target <name>]\n```\n\n### `group get`\nGet group details including membership criteria and effective VM members.\n\n```bash\nvmware-nsx-security group get <group-id> [--target <name>]\n```\n\n### `group delete`\nDelete a security group (checks for DFW references first).\n\n```bash\nvmware-nsx-security group delete <group-id> [--dry-run] [--target <name>]\n```\n\nRefuses deletion if the group is a member of another group, or is\nreferenced by any DFW or gateway-firewall rule (source, destination, or\napplied-to scope) or by a policy-level scope. If the\nreference scan itself fails, deletion is aborted rather than proceeding\nblind.\n\n> Group **creation** (with tag/IP/segment criteria) is exposed via the\n> `create_group` MCP tool. The tag criterion is a Policy Condition with a\n> pipe-delimited value `\"scope|tag\"`; multiple criteria are ORed.\n\n---\n\n## `tag` — VM NSX Tag Management\n\n### `tag list`\nList NSX tags on a VM by display name.\n\n```bash\nvmware-nsx-security tag list <vm-display-name> [--target <name>]\n```\n\n### `tag apply`\nApply an NSX tag to a VM (by external ID).\n\n```bash\nvmware-nsx-security tag apply <vm-external-id> \\\n  --scope <scope> \\\n  --value <value> \\\n  [--dry-run] \\\n  [--target <name>]\n```\n\n| Option | Description |\n|--------|-------------|\n| `--scope` | Tag scope (e.g. `tier`, `env`, `owner`) |\n| `--value` | Tag value (e.g. `web`, `production`) |\n\nAdditive — existing tags on the VM are preserved. Uses\n`POST /api/v1/fabric/virtual-machines?action=add_tags` with body\n`{\"external_id\", \"tags\"}`.\n\n### `tag remove`\nRemove an NSX tag from a VM (by external ID).\n\n```bash\nvmware-nsx-security tag remove <vm-external-id> \\\n  --scope <scope> \\\n  --value <value> \\\n  [--dry-run] \\\n  [--target <name>]\n```\n\n| Option | Description |\n|--------|-------------|\n| `--scope` | Tag scope of the tag to remove |\n| `--value` | Tag value of the tag to remove |\n\nRemoves only the exact scope/value pair; other tags are preserved. May\nchange dynamic security group membership immediately — which is why this\ncommand **asks for confirmation twice**, like the other destructive commands\nhere. It takes no bypass flag, so a script that called it unattended before\nwill now wait for input; use `--dry-run` to preview. Uses\n`POST /api/v1/fabric/virtual-machines?action=remove_tags` with body\n`{\"external_id\", \"tags\"}`.\n\n---\n\n## `traceflow` — Packet Tracing\n\n### `traceflow run`\nInitiate a Traceflow and wait for results.\n\n```bash\nvmware-nsx-security traceflow run <src-lport-id> \\\n  --src-ip <ip> \\\n  --dst-ip <ip> \\\n  [--proto TCP|UDP|ICMP] \\\n  [--dst-port <port>] \\\n  [--target <name>]\n```\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `--src-ip` | required | Source IP for probe packet |\n| `--dst-ip` | required | Destination IP |\n| `--proto` | TCP | Protocol: TCP, UDP, or ICMP |\n| `--dst-port` | 80 | Destination port (TCP/UDP) |\n\nOutput: `operation_state` (`IN_PROGRESS` / `FINISHED` / `FAILED`),\n`observations` discriminated by `resource_type` (e.g.\n`TraceflowObservationForwarded`, `TraceflowObservationDroppedLogical` —\nDropped* entries carry `reason` and `acl_rule_id`), and a `dfw_hits`\nsummary of observations that matched a DFW rule.\n\n---\n\n## `idps` — IDPS Operations\n\n### `idps profiles`\nList all IDPS profiles.\n\n```bash\nvmware-nsx-security idps profiles [--target <name>]\n```\n\n### `idps status`\nGet IDPS signature status and global IDS settings.\n\n```bash\nvmware-nsx-security idps status [--target <name>]\n```\n\nOutput: `signature_status` (scalar fields of the signature bundle status\nresource — field names vary by NSX release) and `settings`\n(`auto_update`, `ids_events_to_syslog`).\n\n---\n\n## `doctor` — Environment Diagnostics\n\nRun pre-flight checks: config file, .env permissions, config parse, passwords, network reachability, NSX authentication, NSX version, MCP server import.\n\n```bash\nvmware-nsx-security doctor [--skip-auth] [--config <path>]\n```\n\n| Option | Description |\n|--------|-------------|\n| `--skip-auth` | Skip authentication tests (network check only) |\n| `--config` | Override config file path |\n\n---\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `VMWARE_NSX_SECURITY_CONFIG` | Path to config YAML file |\n| `VMWARE_NSX_SECURITY_<TARGET>_PASSWORD` | Password for target (hyphens → underscores, uppercase) |\n\n**Password examples**:\n- Target `nsx-prod` → `VMWARE_NSX_SECURITY_NSX_PROD_PASSWORD`\n- Target `nsx-lab` → `VMWARE_NSX_SECURITY_NSX_LAB_PASSWORD`\n\nFile v1.13.0:references/setup-guide.md\n\n# VMware NSX Security — Setup Guide\n\n## Prerequisites\n\n- NSX Manager 3.x or 4.x (NSX-T)\n- An NSX admin account with DFW read/write permissions\n- Python 3.10+ and `uv` installed\n\n## 1. Install\n\n```bash\nuv tool install vmware-nsx-security==1.13.0\n```\n\nVerify:\n```bash\nvmware-nsx-security --help\n```\n\n## 2. Create Config Directory\n\n```bash\nmkdir -p ~/.vmware-nsx-security\n```\n\n## 3. Create Config File\n\nCopy the example and edit:\n\n```bash\n# From the package source directory\ncp config.example.yaml ~/.vmware-nsx-security/config.yaml\n```\n\nOr create manually:\n\n```yaml\n# ~/.vmware-nsx-security/config.yaml\ntargets:\n  nsx-prod:\n    host: nsx-manager.example.com\n    username: admin\n    port: 443\n    verify_ssl: true\n    environment: production   # Which environment this is — see below\n  nsx-lab:\n    host: 10.0.0.50\n    username: admin\n    port: 443\n    verify_ssl: false   # Allow self-signed cert in lab\n    environment: lab\n\ndefault_target: nsx-prod\n```\n\n**`environment` (optional label)**: policy scopes its rules by this value, so an environment-scoped `deny` rule in `~/.vmware/rules.yaml` can match on it — for example, to freeze state-changing writes on `production`. Any label you like works (`production`, `staging`, `lab`, `dc2-prod`); the target's *name* is not used for it.\n\nA target with no label is simply not matched by such a rule. Read-only operations are never affected either way. Run `vmware-audit policy` to see the rules currently in force.\n\n## 4. Set Passwords\n\nPasswords are **never** stored in `config.yaml`. Use environment variables or a `.env` file:\n\n```bash\n# Create .env file\ncat > ~/.vmware-nsx-security/.env << 'EOF'\nVMWARE_NSX_SECURITY_NSX_PROD_PASSWORD=your_prod_password\nVMWARE_NSX_SECURITY_NSX_LAB_PASSWORD=your_lab_password\nEOF\n\n# Secure the file — IMPORTANT\nchmod 600 ~/.vmware-nsx-security/.env\n```\n\n**Password variable naming convention**: `VMWARE_NSX_SECURITY_<TARGET>_PASSWORD`\nwhere `<TARGET>` is the target name uppercased with hyphens → underscores.\n\n## 5. Verify Setup\n\n```bash\nvmware-nsx-security doctor\n```\n\nAll checks should show PASS:\n- Config file\n- .env permissions (owner-only 600)\n- Config parse (N targets configured)\n- Password (set for each target)\n- Network (TCP reachable on port 443)\n- NSX auth (session created)\n- NSX version (vX.Y.Z)\n- MCP server import\n\n## 6. Configure MCP Server\n\n### Claude Code\n\nAdd to `~/.claude.json` (or `.claude.json` in your project):\n\n```json\n{\n  \"mcpServers\": {\n    \"vmware-nsx-security\": {\n      \"command\": \"vmware-nsx-security\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"VMWARE_NSX_SECURITY_CONFIG\": \"~/.vmware-nsx-security/config.yaml\"\n      }\n    }\n  }\n}\n```\n\n### Cursor\n\nIn Cursor Settings → MCP Servers:\n\n```json\n{\n  \"vmware-nsx-security\": {\n    \"command\": \"vmware-nsx-security\",\n    \"args\": [\"mcp\"],\n    \"env\": {\n      \"VMWARE_NSX_SECURITY_CONFIG\": \"${HOME}/.vmware-nsx-security/config.yaml\"\n    }\n  }\n}\n```\n\n### Goose\n\n```json\n{\n  \"mcpServers\": {\n    \"vmware-nsx-security\": {\n      \"command\": \"vmware-nsx-security\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"VMWARE_NSX_SECURITY_CONFIG\": \"~/.vmware-nsx-security/config.yaml\"\n      }\n    }\n  }\n}\n```\n\n> v1.5.15+ recommends the single-command form `vmware-nsx-security mcp`. Pre-1.5.15 used\n> `uvx --from vmware-nsx-security vmware-nsx-security-mcp`, which still works but re-resolves <!-- install-pin: historical -->\n> from PyPI on each launch and breaks behind corporate TLS proxies. The legacy\n> `vmware-nsx-security-mcp` entry point is also kept for backward compatibility.\n\n## 7. Docker (Optional)\n\nBuild and run as a container:\n\n```bash\ndocker-compose up --build\n```\n\nMount your config:\n```yaml\n# docker-compose.yml already mounts ~/.vmware-nsx-security:/root/.vmware-nsx-security:ro\n```\n\n## Companion Skill Setup\n\nFor full NSX coverage, also install:\n\n```bash\n# NSX networking: segments, gateways, NAT, routing\nuv tool install vmware-nsx-mgmt\n\n# vSphere monitoring\nuv tool install vmware-monitor\n```\n\nConfigure each with its own config directory:\n- NSX networking: `~/.vmware-nsx/config.yaml`\n- NSX security: `~/.vmware-nsx-security/config.yaml`\n- Monitor: `~/.vmware-monitor/config.yaml`\n\nBoth `vmware-nsx` and `vmware-nsx-security` can point to the same NSX Manager hosts — the config files are separate because the password env vars differ.\n\n### Password obfuscation at rest\n\nOn first load, any plaintext `*_PASSWORD` value in `.env` is automatically\nrewritten to a grep-safe `b64:<encoded>` form and decoded transparently at\nruntime, so a casual `grep` of the file no longer reveals the password. Values\nare read and written through python-dotenv's own parser, so the stored secret\nnever drifts from what you configured (quotes, inline comments, and trailing\nwhitespace are handled correctly).\n\n> **This is obfuscation, not encryption.** Anyone who can read the file can\n> still decode it. For real secrecy at rest, do not store the password in `.env`\n> at all — inject it from a secret manager (HashiCorp Vault, CyberArk, AWS\n> Secrets Manager, or a Kubernetes Secret) into the `*_PASSWORD` environment\n> variable at process start. The code reads the env var either way.\n\n## Running the Agent Read-Only\n\nTo run the agent read-only, give it a read-only NSX service account (RBAC) — writes are then refused by NSX itself, on every surface, which no env var or config switch could guarantee.\n\n## Security Notes\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"NSX\" are trademarks of Broadcom.\n\n- **Source Code**: Fully open source at [github.com/vmware-skills/VMware-NSX-Security](https://github.com/vmware-skills/VMware-NSX-Security) (MIT). The `uv` installer fetches the `vmware-nsx-security` package from PyPI, which is built from this GitHub repository. We recommend reviewing the source code and commit history before deploying in production.\n- `config.yaml` should be readable only by your user: `chmod 600 ~/.vmware-nsx-security/config.yaml`\n- `.env` must be `chmod 600` — the doctor check warns if it is too permissive\n- Use a dedicated read/write NSX account for security operations, not the global `admin` superuser\n- Audit logs are written to `~/.vmware/audit.db` (SQLite WAL mode, via vmware-policy)\n- The MCP server uses stdio transport — it never opens a network port; it is started on-demand by your AI agent\n\nFile v1.13.0:skill-card.md\n\n## Description:\n\nManages VMware NSX and VMware vDefend security tasks, including distributed firewall policies, security groups, VM tags, Traceflow diagnostics, and IDS/IPS status.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nInfrastructure, network security, and platform engineers use this skill to inspect and administer NSX/vDefend security controls for microsegmentation, firewall rule management, security groups, VM tags, Traceflow troubleshooting, and IDS/IPS checks.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can administer high-impact NSX security controls, including firewall, tag, group, and delete operations.\n\nMitigation: Install only for agents intended to administer NSX security, use a least-privilege NSX account, and review previews before approving firewall, tag, group, or delete operations.\n\nRisk: Credentials and configuration files could expose NSX access if stored with broad local permissions.\n\nMitigation: Prefer secret-manager or process-level environment injection for production, and keep config and environment files owner-only.\n\nRisk: Incorrect distributed-firewall changes can silently permit or block traffic.\n\nMitigation: Use dry runs or delete previews, keep management access rules explicit, verify tags and group membership before enforcement, and use Traceflow to validate proposed rule behavior.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/vmware-nsx-security)\n- [Project homepage](https://github.com/vmware-skills/VMware-NSX-Security)\n- [Capabilities Reference](references/capabilities.md)\n- [Setup Guide](references/setup-guide.md)\n- [CLI Reference](references/cli-reference.md)\n- [Agent Guardrails](references/agent-guardrails.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with inline shell commands and structured tool-result summaries]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [State-changing NSX operations require explicit approval or preview review, and outputs may include current NSX policy, rule, group, tag, Traceflow, and IDPS data.]\n\n## Skill Version(s):\n\n1.13.0 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.13.0:evals/evals.json\n\n{\n  \"skill_name\": \"vmware-nsx-security\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"prompt\": \"Create a firewall rule to block all traffic from the dev segment to the production database VMs\",\n      \"expected_output\": \"DFW rule created with correct source/destination\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses create_dfw_policy or creates within existing policy\",\n        \"Uses create_dfw_rule with correct source and destination groups\",\n        \"Sets action to DROP or REJECT\"\n      ]\n    },\n    {\n      \"id\": 2,\n      \"prompt\": \"Run a traceflow from VM web-01 to VM db-01 on port 3306 to verify MySQL connectivity\",\n      \"expected_output\": \"Traceflow result showing path and allow/deny\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses run_traceflow with correct source, destination, and port\",\n        \"Uses get_traceflow_result to show the path\",\n        \"Reports whether traffic is allowed or blocked\"\n      ]\n    },\n    {\n      \"id\": 3,\n      \"prompt\": \"Create a security group for all web servers and tag VMs web-01, web-02, web-03\",\n      \"expected_output\": \"Security group created, VMs tagged\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses create_group for the security group\",\n        \"Uses apply_vm_tag for each VM\",\n        \"Group membership based on tags\"\n      ]\n    }\n  ]\n}\n\nArchive v1.12.0: 8 files, 27452 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (9340b), references/capabilities.md (15246b), references/cli-reference.md (6939b), references/setup-guide.md (6433b), skill-card.md (2624b), SKILL.md (21125b), _meta.json (139b)\n\nFile v1.12.0:SKILL.md\n\n---\nname: vmware-nsx-security\ndescription: >\n  Use this skill whenever the user needs to manage VMware NSX security (rebranded VMware vDefend in VCF 9) — distributed firewall (DFW) policies, security groups, microsegmentation, and IDS/IPS.\n  Directly handles: create/manage DFW policies and rules, security groups, VM tags, network traceflow diagnostics, IDPS profiles and status.\n  Always use this skill for \"create firewall rule\", \"set up microsegmentation\", \"add VM to security group\", \"run traceflow\", \"check IDS status\", \"vDefend firewall rule\", or any NSX security / vDefend / DFW task.\n  Do NOT use for NSX networking operations like segments, gateways, NAT, or routing (use vmware-nsx), or VM lifecycle (use vmware-aiops).\n  For load balancing/AVI/AKO use vmware-avi.\ninstaller:\n  kind: uv\n  package: vmware-nsx-security\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-nsx-security\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_NSX_SECURITY_CONFIG\",\"VMWARE_NSX_SECURITY_<TARGET>_PASSWORD\",\"VMWARE_NSX_SECURITY_<TARGET>_USERNAME\",\"VMWARE_AUDIT_APPROVED_BY\"],\"bins\":[\"vmware-policy\"]},\"homepage\":\"https://github.com/vmware-skills/VMware-NSX-Security\",\"emoji\":\"🔒\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  vmware-policy auto-installed as Python dependency (provides @vmware_tool decorator and audit logging). All write operations audited to ~/.vmware/audit.db.\n  Credentials: Each NSX Manager target requires a per-target password env var in ~/.vmware-nsx-security/.env following the pattern VMWARE_NSX_SECURITY_<TARGET_NAME_UPPER>_PASSWORD. Passwords are never logged or echoed.\n  Destructive operations: DFW policy delete checks for active rules, security group delete checks for references. The three MCP delete tools preview by default — without confirm=True they return the blast radius and change nothing, and confirm=True is refused while a blocker remains or a read failed. IDS/IPS config changes require double confirmation. Traceflow is read-only.\n  No webhooks, no outbound network calls, no guest operations. Local only: stdio MCP + NSX Policy API (HTTPS 443).\n  Transitive dependencies: Only vmware-policy (audit/policy). No post-install scripts or background services.\n---\n\n# VMware NSX Security\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"NSX\" are trademarks of Broadcom. Source code is publicly auditable at [github.com/vmware-skills/VMware-NSX-Security](https://github.com/vmware-skills/VMware-NSX-Security) under the MIT license.\n\nVMware NSX DFW microsegmentation and security — 22 MCP tools for distributed firewall, security groups, VM tags, the DFW exclusion list, Traceflow, and IDPS.\n\n> Domain-focused security skill for NSX-T / NSX 4.x Policy API.\n> **Companion skills**: [vmware-nsx](https://github.com/vmware-skills/VMware-NSX) (networking), [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (VM lifecycle), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only monitoring), [vmware-avi](https://github.com/vmware-skills/VMware-AVI) (AVI/ALB/AKO), [vmware-harden](https://github.com/vmware-skills/VMware-Harden) (compliance baselines).\n> | [vmware-pilot](../vmware-pilot/SKILL.md) (workflow orchestration) | [vmware-policy](../vmware-policy/SKILL.md) (audit/policy)\n\n## What This Skill Does\n\n| Category | Tools | Count |\n|----------|-------|:-----:|\n| **DFW Policy** | list, get, create, update, delete, list rules | 6 |\n| **DFW Rules** | create, update, delete, get stats | 4 |\n| **Security Groups** | list, get, create, delete | 4 |\n| **VM Tags** | list VM tags, apply tag, remove tag | 3 |\n| **Traceflow** | run trace, get result | 2 |\n| **IDPS** | list profiles, get status | 2 |\n| **DFW Exclusions** | list excluded members | 1 |\n\n**Total**: 22 tools (11 read-only + 11 write)\n\n## Quick Install\n\n```bash\nuv tool install vmware-nsx-security==1.12.0\nvmware-nsx-security init      # guided setup: writes config + .env (chmod 600, password grep-safe), then verifies\nvmware-nsx-security doctor\n```\n\n## When to Use This Skill\n\n- List, create, or modify DFW security policies and rules\n- Create security groups based on VM tags, IP ranges, or segment membership\n- Apply or list NSX tags on virtual machines\n- Run Traceflow to trace a packet path and diagnose drop reasons\n- Check IDPS profile configuration, signature status, and global IDS settings\n- Implement zero-trust microsegmentation between application tiers\n- Check the DFW exclusion list — which VMs no distributed-firewall rule reaches\n\n**Use companion skills for**:\n- NSX segments, gateways, NAT, routing, IPAM → `vmware-nsx`\n- VM lifecycle, deployment, guest ops → `vmware-aiops`\n- vSphere inventory, health, alarms, events → `vmware-monitor`\n- Storage: iSCSI, vSAN, datastores → `vmware-storage`\n- Tanzu Kubernetes → `vmware-vks`\n- Load balancing, AVI/ALB, AKO, Ingress → `vmware-avi`\n\n## Related Skills — Skill Routing\n\n| User Intent | Recommended Skill |\n|-------------|-------------------|\n| NSX security: DFW rules, security groups, IDS/IPS | **vmware-nsx-security** ← this skill |\n| NSX networking: segments, gateways, NAT, routing | **vmware-nsx** |\n| Read-only vSphere monitoring, alarms, events | **vmware-monitor** |\n| VM lifecycle, deployment, guest ops | **vmware-aiops** |\n| Storage: iSCSI, vSAN, datastores | **vmware-storage** |\n| Tanzu Kubernetes | **vmware-vks** |\n| Multi-step workflows with approval | **vmware-pilot** |\n| Compliance baselines (CIS / 等保 / PCI-DSS), drift detection, LLM remediation advisor | **vmware-harden** (`uv tool install vmware-harden`) |\n| Load balancer, AVI, ALB, AKO, Ingress | **vmware-avi** (`uv tool install vmware-avi`) |\n| Audit log query | **vmware-policy** (`vmware-audit` CLI) |\n\n## Common Workflows\n\n### Implement App-Tier Microsegmentation\n\n**Pre-flight (judgment — DFW changes can lock everyone out)**:\n- **Default-allow first**: the very first rule in any new policy must be ALLOW for management traffic (DNS, NTP, vCenter, SSH from jumphost). Without it, the moment you add a default-deny you blackhole your own access.\n- Tag inventory: confirm the VMs you intend to protect actually carry the tag (`tag list <vm>`). A group based on a non-existent tag matches zero VMs — the policy will appear \"applied\" but enforce nothing.\n- Category choice: `Application` for app-tier microseg (rules evaluated late, after Infrastructure rules pass through). Using `Emergency` for routine rules will starve real incident-response capacity.\n- Stateless? Default to stateful — NSX DFW is stateful and almost no rule should be stateless. Stateless = both directions must be explicitly allowed.\n- Always start with **logging enabled** on new rules; disable later once verified. Silent drops are the worst kind of bug.\n\n**Steps**:\n1. Tag the VMs first (see workflow below) — empty groups = no enforcement\n2. Create groups via the `create_group` MCP tool with `tag_scope`/`tag_value` (the tag condition is matched as `\"scope|tag\"`, e.g. `tier|web`; note multiple criteria types — tag/IP/segment — are ORed, not ANDed)\n3. `policy create app-microseg --category Application`\n4. Add rules in order: ALLOW management → ALLOW intra-tier → ALLOW web→app on app-port → DROP any-any with logging\n5. Verify with traceflow (see below) **before** enabling default-deny\n\n### Answer \"is this VM protected by the DFW?\"\n\nNever from the policy and rule listings alone. A VM on the **DFW exclusion list**\nhas no distributed firewall in its datapath: the rules that name it exist and\nnone of them applies. On a VCF estate the management VMs (vCenter, VCF\nOperations, NSX managers) are commonly excluded — one real 9.1 fabric had 10 of\n12 hosts on that list.\n\n1. `list_dfw_exclusions` — the whole list, resolved to the VMs in each group.\n   Check `scope`: `\"user\"` means system-owned exclusions are **not** in the\n   answer, so an empty list there is not proof of anything.\n2. `list_vm_tags <vm>` — `dfw_excluded` is the per-VM verdict. `true` means no\n   rule reaches it; `null` means the list could not be read, which is **not**\n   `false`, so say \"unknown\" rather than \"protected\".\n3. Only then read `list_dfw_policies` / `list_dfw_rules` for what is enforced on\n   the VMs that are not excluded. That listing carries `exclusion_note` whenever\n   anything is on the list.\n\n### Apply NSX Tags to VMs\n\n**Judgment**: tags drive group membership which drives DFW enforcement. A misspelled tag silently excludes a VM from protection. Always re-list after applying.\n\n1. `tag list my-web-vm-01` → record the VM external ID, also see what tags already exist (avoid duplicates / typo collisions)\n2. `tag apply <vm-external-id> --scope tier --value web`\n3. **Verify**: `tag list my-web-vm-01` again → confirm the new tag is present AND no unexpected ones\n\n### Trace a Packet with Traceflow\n\n**Judgment**: traceflow is your verification mechanism for any DFW change. Run it **before** enabling deny rules and **after** every rule modification. Don't trust \"looks right in the UI.\"\n\n1. Get source VM's logical port ID via `vmware-nsx troubleshoot vm-segment`\n2. `traceflow run <lport-id> --src-ip <src> --dst-ip <dst> --proto TCP --dst-port <port>`\n3. Inspect the DFW hit chain: which rule matched, ALLOW or DROP, and at which transport node\n4. **Common failure**: rule matches at category Application but is shadowed by an earlier DROP at category Environment — read the trace top-to-bottom, not just the final verdict\n\n### Check DFW Policy Hit Counts\n\n```bash\nvmware-nsx-security policy list\nvmware-nsx-security rule list <policy-id>\nvmware-nsx-security rule stats <policy-id> <rule-id>\n```\n\n### Multi-Target Operations\n\nAll commands accept `--target <name>` to operate against a specific NSX Manager:\n\n```bash\n# Default target\nvmware-nsx-security policy list\n\n# Specific target\nvmware-nsx-security policy list --target nsx-prod\nvmware-nsx-security group list --target nsx-lab\n```\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models (Ollama, Qwen) | **CLI** | ~2K tokens vs ~8K for MCP |\n| Cloud models (Claude, GPT-4o) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | Type-safe parameters, structured output |\n\nRunning with local or small models? See [`references/agent-guardrails.md`](references/agent-guardrails.md) for explicit operating rules.\n\n## MCP Tools (22 — 11 read, 11 write)\n\nAll MCP tools accept an optional `target` parameter.\n\n`list_dfw_policies`, `list_dfw_rules`, `list_groups` and `list_idps_profiles` return the family\nlist envelope — `{items, returned, limit, total, truncated, hint}` — rather than a bare array.\nRead the rows from `items` and check `truncated` before concluding a listing is complete; a\n50-row default page looks identical to a whole estate without it. `total` is stated only where\nthe scan proved it: it is the real count on an unfiltered listing that stayed under the\n1000-item `get_all` cap, and `null` for name-filtered listings, capped scans, and\n`list_dfw_rules` (whose fetch is bounded to the requested window). `truncated` says `items` is not the whole\ncollection; it is still true on the last page of a walk, so page with `next_offset` and stop\nwhen it is `null`, never on `truncated`. The `hint` says which of the two you are looking at.\nErrors return\n`{error, hint}` (a dict, not a one-element list).\n\n| Category | Tool | Type | Description |\n|----------|------|:----:|-------------|\n| DFW Exclusions | `list_dfw_exclusions` | Read | List the DFW exclusion list — members no DFW rule reaches. Read this before calling any VM micro-segmented |\n| DFW Policy | `list_dfw_policies` | Read | List all DFW security policies with category, sequence, and rule count |\n| | `get_dfw_policy` | Read | Get policy details: category, stateful, locked, scope, tags |\n| | `create_dfw_policy` | Write | Create a new DFW policy with category and sequence number |\n| | `update_dfw_policy` | Write | Partial update: display_name, description, sequence_number, stateful |\n| | `delete_dfw_policy` | Write | Delete policy — previews unless `confirm=True`; refuses if active rules exist |\n| | `list_dfw_rules` | Read | List rules in a policy: action, sources, destinations, services |\n| DFW Rules | `create_dfw_rule` | Write | Create rule with sources/destinations/services/action/scope |\n| | `update_dfw_rule` | Write | Partial update rule fields |\n| | `delete_dfw_rule` | Write | Delete a rule from a policy — previews unless `confirm=True` |\n| | `get_dfw_rule_stats` | Read | Get packet/byte/session/hit counts and popularity_index for a rule |\n| Security Groups | `list_groups` | Read | List all security groups with expression count |\n| | `get_group` | Read | Get group details: expression criteria + up to 50 effective VM members |\n| | `create_group` | Write | Create group with tag/IP/segment membership criteria (tag matched as \"scope\\|tag\"; multiple criteria ORed) |\n| | `delete_group` | Write | Delete group — previews unless `confirm=True`; refuses if referenced by rules/scopes or a parent group, or if the scan fails |\n| VM Tags | `list_vm_tags` | Read | List NSX tags on a VM by display name |\n| | `apply_vm_tag` | Write | Apply a scope/value tag to a VM (additive, preserves existing tags) |\n| | `remove_vm_tag` | Write | Remove a scope/value tag from a VM (other tags preserved; may change dynamic group membership) |\n| Traceflow | `run_traceflow` | Write | Inject probe packet; returns operation_state + hop-by-hop observations (by resource_type) + dfw_hits |\n| | `get_traceflow_result` | Read | Check operation_state/observations of an existing traceflow |\n| IDPS | `list_idps_profiles` | Read | List IDPS profiles with severity and filter criteria |\n| | `get_idps_status` | Read | Get IDPS signature status + global IDS settings (auto_update, syslog export) |\n\nThe three `delete_*` tools preview by default: without `confirm=True` they return `blast_radius` — the object, what it holds or matches (a policy's `rule_count`, a rule's action, sources, destinations and services, a group's `references`), `blockers` and `unmeasured` — and delete nothing. Show it to the user and pass `confirm=True` only after they decide; it is refused while a blocker remains or a read failed.\n\n## CLI Quick Reference\n\n```bash\n# DFW Policy\nvmware-nsx-security policy list [--target <name>]\nvmware-nsx-security policy get <policy-id>\nvmware-nsx-security policy create <id> --name \"Display Name\" --category Application [--dry-run]\nvmware-nsx-security policy delete <id> [--dry-run]\n\n# DFW Rules\nvmware-nsx-security rule list <policy-id>\nvmware-nsx-security rule stats <policy-id> <rule-id>\nvmware-nsx-security rule delete <policy-id> <rule-id> [--dry-run]\n\n# Security Groups\nvmware-nsx-security group list\nvmware-nsx-security group get <group-id>\nvmware-nsx-security group delete <group-id> [--dry-run]\n\n# Tags\nvmware-nsx-security tag list <vm-display-name>\nvmware-nsx-security tag apply <vm-external-id> --scope env --value production [--dry-run]\nvmware-nsx-security tag remove <vm-external-id> --scope env --value production [--dry-run]\n\n# Traceflow\nvmware-nsx-security traceflow run <lport-id> --src-ip &lt;src-ip&gt; --dst-ip &lt;dst-ip&gt;\n\n# IDPS\nvmware-nsx-security idps profiles\nvmware-nsx-security idps status\n\n# Diagnostics\nvmware-nsx-security doctor [--skip-auth]\n```\n\n## Troubleshooting\n\n### \"Cannot delete policy — active rules exist\"\n\n`delete_dfw_policy` checks for active rules before deleting. Use `vmware-nsx-security rule list <policy-id>` to see which rules need to be removed first. Then delete each rule individually before retrying the policy deletion.\n\n### \"Cannot delete group — referenced by DFW rules\"\n\n`delete_group` scans DFW and gateway policies for the group in rule source_groups, destination_groups and applied-to scope, plus policy-level scope, and checks parent groups. Remove the group from those references first (via `update_dfw_rule` replacing the group path with 'ANY' or another group), then retry. If the error says the reference scan itself failed, deletion was aborted as a precaution — verify NSX connectivity with `vmware-nsx-security doctor` and retry.\n\n### \"No virtual machine named ... exists in the NSX fabric inventory\"\n\n`list_vm_tags` looks up VMs by display name via the NSX fabric API. Common causes:\n1. Display name mismatch — the name in NSX Manager may differ from vCenter. Check `vmware-monitor vm list` for the exact NSX fabric display name.\n2. VM not registered — newly deployed VMs may take a minute to appear in the NSX fabric.\n3. Multiple VMs with the same name — use `apply_vm_tag` with the specific external_id.\n\n### Traceflow returns empty observations\n\n1. If `operation_state` is `IN_PROGRESS`, the trace has not finished — poll again with `get_traceflow_result <traceflow-id>`.\n2. Verify the `src_lport_id` is the correct logical port attachment UUID — not the segment port path. Get it from `vmware-nsx troubleshoot vm-segment <vm>`.\n3. The source VM must be powered on and connected to an NSX overlay segment.\n4. If the VM is on a VLAN-backed segment, Traceflow is not supported.\n5. NSX Manager requires the transport node hosting the source VM to be reachable. Check `vmware-nsx health transport-nodes`.\n\n### DFW rule stats show zero hits\n\nA newly created rule will have zero hit counts until traffic matches it. If expected traffic still shows zero:\n1. Confirm the rule is not disabled (`disabled: false` in `list_dfw_rules` output).\n2. Check that source/destination group membership is correct using `get_group`.\n3. Verify rule sequence number — a lower-sequence rule with ALLOW/DROP may be matching first.\n\n### \"Password not found\" error\n\nPassword variable convention: `VMWARE_NSX_SECURITY_<TARGET_UPPER>_PASSWORD`\nwhere hyphens are replaced by underscores. For target `nsx-prod`:\n`VMWARE_NSX_SECURITY_NSX_PROD_PASSWORD`. Check `~/.vmware-nsx-security/.env`.\n\n### `invalid peer certificate: UnknownIssuer` (uvx)\n\nCorporate TLS proxy not trusted by uv's bundled cert store. Use the v1.5.15+\nsingle-command form `vmware-nsx-security mcp` (no PyPI re-resolve), or\n`export UV_NATIVE_TLS=true` to make uv use the system cert store.\n\n## Safety\n\n- **Audit logging**: All write operations logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy) with timestamp, user, target, operation, parameters, and result\n- **Dependency checks**: `delete_dfw_policy` checks for active rules; `delete_group` checks for DFW rule references — prevents accidental cascade failures\n- **MCP delete preview**: the three MCP delete tools act only with `confirm=True`; a bare call returns the blast radius and deletes nothing\n- **Input validation**: All IDs validated against safe character set (alphanumerics, hyphens, underscores, dots); all text fields sanitized to strip control characters\n- **Dry-run mode**: CLI write commands support `--dry-run` to preview API calls without executing\n- **Double confirmation**: CLI destructive operations (delete) require two separate confirmation prompts\n- **Credential safety**: Passwords loaded only from environment variables (`.env` file), never from `config.yaml`\n- **No networking changes**: Cannot modify segments, gateways, NAT, or routing — that scope belongs to `vmware-nsx`\n- **Prompt injection defense**: All API-sourced strings passed through `_sanitize()` before inclusion in tool output\n\n## Setup\n\n```bash\nuv tool install vmware-nsx-security==1.12.0\nmkdir -p ~/.vmware-nsx-security\ncp config.example.yaml ~/.vmware-nsx-security/config.yaml\n# Edit config.yaml with your NSX Manager targets\n\n# Add to ~/.vmware-nsx-security/.env (create if missing, chmod 600):\n# VMWARE_NSX_SECURITY_NSX_PROD_PASSWORD=<your-password>\nchmod 600 ~/.vmware-nsx-security/.env\n\nvmware-nsx-security doctor\n```\n\n> All tools are automatically audited via vmware-policy. Audit logs: `vmware-audit log --last 20`\n\n> Full setup guide: see `references/setup-guide.md`\n\n## Architecture\n\n```\nUser (natural language)\n  |\nAI Agent (Claude Code / Goose / Cursor)\n  | reads SKILL.md\nvmware-nsx-security CLI or MCP server (stdio transport)\n  | NSX Policy API (REST/JSON over HTTPS)\nNSX Manager\n  |\nDFW Policies / Rules / Security Groups / Tags / IDPS\n```\n\nThe MCP server uses stdio transport (local only, no network listener). All connections to NSX Manager use HTTPS on port 443.\n\n## Audit & Safety\n\nAll operations are automatically audited via vmware-policy (`@vmware_tool` decorator):\n- Every tool call logged to `~/.vmware/audit.db` (SQLite, framework-agnostic)\n- Policy rules enforced via `~/.vmware/rules.yaml` (deny rules, maintenance windows, risk levels)\n- Risk classification: each tool tagged as low/medium/high/critical\n- View recent operations: `vmware-audit log --last 20`\n- View denied operations: `vmware-audit log --status denied`\n\nvmware-policy is automatically installed as a dependency — no manual setup needed.\n\n## License\n\nMIT — [github.com/vmware-skills/VMware-NSX-Security](https://github.com/vmware-skills/VMware-NSX-Security)\n\nFile v1.12.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-nsx-security\",\n  \"version\": \"1.12.0\",\n  \"publishedAt\": 1789790132188\n}\n\nFile v1.12.0:references/agent-guardrails.md\n\n# Operating vmware-nsx-security with a local / small model\n\nClaude-class models drive this skill without special instruction. Smaller and\nlocally-hosted models — Llama 3.3 70B, Qwen, Mistral, and similar, served\nthrough Goose, Ollama, or OpenShift AI — need explicit operating rules to call\ntools reliably.\n\nThis page exists because an operator wrote those rules by hand first. The\nguardrails below are adapted, with thanks, from the working configuration\n[@juanpf-ha](https://github.com/juanpf-ha) developed while running\nvmware-monitor and vmware-aria against a production vSphere estate with Llama\n3.3 70B FP8 on an on-prem H100\n([VMware-AIops#31](https://github.com/vmware-skills/VMware-AIops/issues/31)). The\ncross-skill rules are identical across this family; the parts below marked\nvmware-nsx-security are specific to this skill.\n\nvmware-nsx-security exposes 22 MCP tools, 11 of which change state. This is a\nfirewall: a wrong rule does not raise an error, it silently permits or blocks\ntraffic, and nobody finds out until something breaks or nothing does.\n\n> **Disclaimer**: This is a community-maintained open-source project and is\n> **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom\n> Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom.\n\n---\n\n## First: the rules you no longer need to write\n\nSeveral guardrails from the original configuration are now enforced by the\nskill itself. Prompt instructions are advisory — a model can ignore them.\nThese are structural, so it cannot.\n\n| Guardrail you would otherwise prompt for | Now enforced by |\n|---|---|\n| \"Check whether a group is used anywhere before deleting it\" | **`delete_group` scans** DFW and gateway-firewall rule sources, destinations, applied-to scope and policy scope, plus parent groups, and refuses when referenced. It also refuses when the scan itself fails, rather than assuming the group is unused. |\n| \"Do not delete a policy that still has rules in it\" | **`delete_dfw_policy` refuses** while active rules exist. |\n| \"Show me what a delete would remove before it happens\" | **The three delete tools preview by default.** Without `confirm=True` they return `blast_radius` and delete nothing; `confirm=True` is refused while a blocker remains or a read failed. Pass it only after the user has seen the preview. |\n| \"Use explicit limits for queries that may return large amounts of data\" | **The list envelope.** `list_dfw_policies`, `list_dfw_rules`, `list_groups` and `list_idps_profiles` return `{items, returned, limit, total, truncated, hint}`, so the model reads truncation instead of guessing at it. A 50-row default page and a whole estate look identical without it. |\n| \"If a listing came back empty, say so rather than claiming the call failed\" | Same envelope. Empty `items` with `truncated: false` means checked-and-none — a stated result, not a silence the model has to interpret. Note `total` is `null` for name-filtered and capped listings; `truncated: true` means `items` is not the whole collection and stays true on the last page, so page with `next_offset` and stop when it is `null`. |\n| \"Log every state change you make\" | **The `@vmware_tool` decorator.** Every write is recorded to `~/.vmware/audit.db` before the model sees the result, and policy rules are evaluated ahead of execution. |\n| \"Block state-changing writes against a production target\" | **Policy.** An opt-in environment-scoped `deny` rule in `~/.vmware/rules.yaml` matches a target's `environment:` label and refuses matching writes before execution. |\n\n---\n\n## The system prompt\n\nEverything below still benefits from being stated explicitly. Copy this into\nyour agent's instruction block.\n\n```text\n## Tool use\n\n- Always call an MCP tool before answering any question about the current NSX\n  environment. Never answer from memory or assumption.\n- Never describe a tool call, and never output a JSON example, instead of\n  executing the tool. If you intend to call a tool, call it.\n- If a tool fails, report the actual error text. Do not complete the answer\n  with assumptions about what the result would have been.\n- Use explicit limits on queries that may return large amounts of data. Do not\n  request unlimited results unless the user asks for them.\n- Every tool accepts an optional target. When more than one NSX Manager is\n  configured, name the target explicitly rather than relying on the default.\n\n## Skill routing\n\n- vmware-nsx-security: DFW policies and rules, security groups, VM tags,\n  IDS/IPS profiles and status, Traceflow.\n- vmware-nsx: segments, Tier-0 and Tier-1 gateways, BGP, NAT, static routes,\n  IP pools, transport nodes. Routing and switching are not this skill.\n- vmware-monitor: read-only vCenter inventory, hosts, alarms, events.\n- vmware-aiops: VM lifecycle.\n- vmware-harden: compliance baselines and drift, including firewall posture.\n- vmware-pilot: multi-step workflows that need approval gates.\n\n## Data fidelity\n\n- Never invent policies, rules, groups, tags, IP addresses or services. If a\n  tool did not return it, it does not exist for this answer.\n- Preserve the exact action, direction, disabled flag, category and sequence\n  values the tools return. Do not translate, normalise, or prettify enum\n  values, and never render ALLOW as \"allowed\" or DROP as \"blocked\".\n- Report every rule field the user asked for, in the order returned. Rule\n  evaluation is order-dependent, so a reordered list is a wrong answer.\n- If a requested field was not returned, show it as \"not available\". Do not\n  infer it from other fields.\n- When a response is long, report every item it contains. If a result is\n  truncated, the tool says so explicitly — report the truncation rather than\n  describing the visible subset as the whole.\n\n## Analysis discipline\n\n- Separate observed data from interpretation. State which is which.\n- Do not claim a security exposure unless the tool output contains explicit\n  supporting evidence. An absent rule is not proof traffic is permitted; a\n  zero hit count is not proof a rule is unused.\n- Avoid generic recommendations that are not directly supported by the results.\n- Never state that a change \"will not affect existing traffic\". You cannot\n  know that from the tool output.\n\n## Writes in vmware-nsx-security\n\n- run_traceflow is a write: it injects a probe packet. Do not call it to\n  \"just check\" something.\n- Sequence number decides which rule matches first. State the sequence you are\n  proposing and what it will sit before and after.\n- Tag membership is matched as \"scope|tag\", and multiple criteria are ORed.\n  Read get_group before assuming what a group contains.\n- remove_vm_tag can change dynamic group membership, and therefore which rules\n  apply to a VM. Say so before proposing it.\n- get_group returns at most 50 effective members. member_count is the group's\n  real size, and members.truncated says whether the sample withheld any — read\n  those two rather than counting members.items.\n```\n\n---\n\n## Known failure modes on small models\n\nObserved with Llama 3.3 70B FP8 (Goose, on-prem H100), and useful as a\nchecklist when evaluating any local model against these skills:\n\n| Symptom | Mitigation |\n|---|---|\n| Describes a tool call, or emits a JSON example, instead of executing it | The \"never describe a tool call\" rule above. Also check your harness is not echoing tool schemas into context — models imitate the nearest format they see. |\n| Long tool responses: omits items, or reports \"no data returned\" when data was present | Ask for explicit limits so responses stay small. Check the envelope's `truncated` / `returned` / `total` fields rather than trusting the model's summary — a \"no data\" claim is checkable against `returned`. A dropped rule in a firewall listing is a security answer that is quietly wrong. |\n| Adds generic recommendations unsupported by results | The \"analysis discipline\" rules. Firewall output attracts invented advice (\"consider tightening this rule\") more than anything else in the family. |\n| Drops requested fields or reorders results | State the required fields and ordering in the request itself. Rule order is semantic here, not cosmetic. |\n| Multi-tool workflows take 30–50s end to end | `get_dfw_policy` and `get_group` each answer a whole question in one call. Fetch the policy once and read its rules from that result rather than looping. |\n| Calls `run_traceflow` believing it to be a read | The rule above. Its name suggests a query; its effect is an injected packet. |\n| Reads a zero hit count as \"this rule is unused\" and proposes deleting it | The \"zero hit count is not proof\" rule. A new rule has zero hits by construction. |\n| Summarises ALLOW/DROP into prose and inverts the meaning | The \"never render ALLOW as allowed\" rule. Keep the enum verbatim. |\n| Retries a refused deletion, or works around it by deleting the references first | The refusals are guards. Report the reason and let a human decide. |\n\n## Reporting results\n\nLocal-model compatibility is an explicit design constraint for this family, and\nthe evidence base is small. If you evaluate a model against this skill —\nQwen, Mistral, Granite, or anything else — a report of what worked and what did\nnot is genuinely useful:\n[github.com/vmware-skills/VMware-NSX-Security/issues](https://github.com/vmware-skills/VMware-NSX-Security/issues).\n\nFile v1.12.0:references/capabilities.md\n\n# VMware NSX Security — Capabilities Reference\n\n## Automation Level Reference\n\nEach operation is classified by autonomy level per the Enterprise Harness Engineering framework:\n\n| Level | Meaning | Agent autonomy | Examples in this skill |\n|:-:|---|---|---|\n| **L1** | Read-only, raw data | Always auto-run | `list_dfw_policies`, `get_dfw_policy`, `list_dfw_rules`, `get_dfw_rule_stats`, `list_groups`, `get_group`, `list_vm_tags`, `get_traceflow_result`, `list_idps_profiles`, `get_idps_status` |\n| **L2** | Read + analysis / recommendation | Always auto-run | DFW rule conflict detection, shadowed-rule analysis, security group reference graph, traceflow path interpretation |\n| **L3** | Single write — user must approve | Only after explicit confirmation; destructive CLI ops require double-confirm + `--dry-run`; the three MCP deletes preview by default and act only with `confirm=True` | `create_dfw_policy`, `create_dfw_rule`, `delete_dfw_rule`, `create_group`, `delete_group`, `apply_vm_tag`/`remove_vm_tag`, `run_traceflow` (injects a synthetic packet) |\n| **L4** | Multi-step plan / apply workflow | Plan generation auto; apply gated by user approval | *(roadmap — staged microsegmentation rollouts, emergency-block playbooks)* |\n| **L5** | Auto-remediation from learned pattern | Pattern library only; requires `risk:low` + `reversible:true` + `repeatable:true` | *(roadmap — candidates: orphaned-SG cleanup, expired temp-block rule removal)* |\n\n**Notes**:\n- L1/L2 tools are always safe for agents to call without confirmation.\n- **List envelope**: `list_dfw_policies`, `list_dfw_rules`, `list_groups` and `list_idps_profiles` return `{items, returned, limit, total, truncated, hint}` instead of a bare array, so an agent can tell a complete answer from a first page rather than inferring it (VMware-AIops issue #31). `total` is reported only where the scan proved it — the real count on an unfiltered listing under the 1000-item `get_all` cap; `null` for name-filtered listings (the Search API returns matches, not a countable set), for scans that stopped at the cap, and for `list_dfw_rules` (bounded to `offset + limit` by design). Page with the `next_offset` extra — pass it back as `offset` and stop when it is `null`. Never loop on `truncated`: it answers \"is `items` the whole collection?\", which is still `true` on the last page of a walk. The `hint` distinguishes them — mid-walk it names the next offset; on the last page it says there is no next page; past the end it says so and points back to offset 0. It never advises raising a limit that cannot return another row.\n- **`rule_count` on `list_dfw_policies`**: an int where NSX reported one, `null` where it did not — `null` means \"not retrieved\", never \"no rules\". The unfiltered listing asks for the count via `include_rule_count` (NSX omits the field otherwise); a name-filtered listing is resolved through the Policy Search API, which carries no rule counts, so every count there reads `null`. Any `null` adds a `rule_count_note` to the envelope. To find out what a `null` policy enforces, call `list_dfw_rules` on it — never read `null` as an empty policy.\n- L3 tools always pass through the `@vmware_tool` decorator: connection check → policy check → audit log → double-confirm. DFW policy delete additionally checks for active rules; SG delete checks for references.\n- **MCP deletes preview by default** (`delete_dfw_policy`, `delete_dfw_rule`, `delete_group`). A call without `confirm=True` reads what the delete would remove and returns `{\"action\": \"preview\", \"blast_radius\": {...}}`, deleting nothing. `blast_radius` names the object and what it measured — a policy's category, `rule_count` and `rule_ids`; a rule's parent policy, action, sources, destinations, services, scope and direction; a group's `expression_count`, `reference_count` and `references` — plus `blockers` and `unmeasured`. `confirm=True` re-measures and is refused, deleting nothing, while a blocker remains (rules left in the policy, entities referencing the group) or while any of those reads failed; the refusal is `{\"error\", \"hint\", \"blast_radius\"}`. Show the preview to the user; set `confirm=True` only after they decide — not because they asked for the delete before seeing it. The preview is logged to the skill audit log as `preview`, not `ok`.\n- For Segment/Gateway/NAT (network plane) see [vmware-nsx](https://github.com/vmware-skills/VMware-NSX).\n\n## DFW Policy Categories\n\nNSX DFW policies are evaluated in category order (lower category = higher priority):\n\n| Category | Priority | Typical Use |\n|----------|:--------:|-------------|\n| Ethernet | 1 | Layer-2 rules (MAC-based) |\n| Emergency | 2 | Incident response — block specific IPs or VMs immediately |\n| Infrastructure | 3 | DNS, NTP, vCenter management traffic |\n| Environment | 4 | Cross-environment rules (e.g. prod → lab) |\n| Application | 5 | Application-tier microsegmentation (most common) |\n\n`create_dfw_policy` validates the category and rejects anything outside this set.\n\n## DFW Rule Actions\n\n| Action | Behaviour |\n|--------|-----------|\n| ALLOW | Permit the traffic |\n| DROP | Silently discard the packet (no RST/ICMP) |\n| REJECT | Discard + send TCP RST or ICMP unreachable |\n| JUMP_TO_APPLICATION | Skip to Application category rules — only valid in policies whose category is Environment |\n\n## DFW Rule Statistics Fields\n\n`get_dfw_rule_stats` aggregates the per-enforcement-point `RuleStatistics`\narray: `packet_count`, `byte_count`, `session_count`, `hit_count` (summed)\nand `popularity_index` (max). There is no `population_count` field in the\nNSX API.\n\n## Security Group Expression Types\n\nGroups support three membership condition types:\n\n| Type | Parameter | Example |\n|------|-----------|---------|\n| Tag Condition | `tag_scope` + `tag_value` | scope=tier, value=web |\n| IP Address | `ip_addresses` | ['10.0.1.0/24', '10.0.2.5'] |\n| Segment Path | `segment_paths` | ['/infra/segments/web-seg'] |\n\nThe tag Condition is sent as a Policy `Condition` with a pipe-delimited\n`value` of `\"scope|tag\"` (e.g. `tier|web`; tag-only matching uses `\"|tag\"`).\n\nMultiple criteria in one group are **ORed** (VM matches ANY condition):\nNSX only permits AND between Conditions of the same member type, so\nheterogeneous expression types (Condition vs IPAddressExpression vs\nPathExpression) must join with OR.\n\n## Traceflow Packet Types\n\nThe probe is a `FieldsPacketData` with nested `ip_header` (src_ip, dst_ip,\nttl, protocol number) and `transport_header`; `transport_type` is the L2\ndelivery mode (`UNICAST`), not the protocol.\n\n| Protocol | transport_header | Notes |\n|----------|------------------|-------|\n| TCP | `tcp_header` (src_port, dst_port) | SYN flag set automatically |\n| UDP | `udp_header` (src_port, dst_port) | |\n| ICMP | `icmp_echo_request_header` | Echo request |\n\nCompletion is polled via `operation_state`: `IN_PROGRESS` → `FINISHED`\nor `FAILED`.\n\n## Traceflow Observation Types\n\nObservations are discriminated by `resource_type`:\n\n| resource_type | Meaning |\n|---------------|---------|\n| TraceflowObservationForwarded | Packet forwarded to next hop |\n| TraceflowObservationDropped / TraceflowObservationDroppedLogical | Packet dropped at this component (carries `reason` + `acl_rule_id`) |\n| TraceflowObservationDelivered | Packet delivered to destination |\n| TraceflowObservationReceived | Packet received at a component |\n\nAny observation carrying an `acl_rule_id` (forwarded or dropped by a DFW\nrule) is also summarised in the `dfw_hits` list of the result.\n\n## IDPS Status Output\n\n`get_idps_status` reads two Policy API resources and returns:\n\n- `signature_status` — scalar fields of the signature bundle status\n  resource (e.g. version / update state; exact field names vary by NSX\n  release, so scalars are passed through as-is)\n- `settings` — `auto_update` (automatic signature updates) and\n  `ids_events_to_syslog` from the global IdsSettings resource\n\nIDPS profile `criteria` are polymorphic `filter_name`/`filter_value`\npairs (ATTACK_TYPE, ATTACK_TARGET, CVSS, PRODUCT_AFFECTED); conjunction\nentries between them are always AND and are omitted from parsed output.\n\n## IDPS Severity Levels\n\nNSX IDPS signatures are classified by severity:\n\n| Level | Score Range | Description |\n|-------|-------------|-------------|\n| CRITICAL | 9.0–10.0 | Immediate exploitation, remote code execution |\n| HIGH | 7.0–8.9 | Significant risk, exploitable vulnerabilities |\n| MEDIUM | 4.0–6.9 | Moderate risk, requires specific conditions |\n| LOW | 0.1–3.9 | Informational, denial-of-service potential |\n\n## NSX Tag Conventions\n\nBest practice for NSX tag design:\n\n| Scope | Example Values | Used For |\n|-------|---------------|----------|\n| `tier` | web, app, db | Application tier microsegmentation |\n| `env` | prod, staging, dev | Environment separation |\n| `owner` | team-a, finance | Policy ownership |\n| `compliance` | pci, hipaa | Regulatory scope |\n\n## API Endpoints Reference\n\n| Operation | Method | Path |\n|-----------|--------|------|\n| List policies | GET | /policy/api/v1/infra/domains/default/security-policies |\n| Get policy | GET | /policy/api/v1/infra/domains/default/security-policies/{id} |\n| Create/replace policy | PUT | /policy/api/v1/infra/domains/default/security-policies/{id} |\n| Update policy | PATCH | /policy/api/v1/infra/domains/default/security-policies/{id} |\n| Delete policy | DELETE | /policy/api/v1/infra/domains/default/security-policies/{id} (MCP first GETs the policy and walks its `/rules`) |\n| List rules | GET | /policy/api/v1/infra/domains/default/security-policies/{id}/rules |\n| Create/replace rule | PUT | .../rules/{rule-id} |\n| Update rule | PATCH | .../rules/{rule-id} |\n| Delete rule | DELETE | .../rules/{rule-id} (MCP first GETs the policy and walks its `/rules` for the rule) |\n| Rule statistics | GET | .../rules/{rule-id}/statistics |\n| List groups | GET | /policy/api/v1/infra/domains/default/groups |\n| Get group | GET | /policy/api/v1/infra/domains/default/groups/{id} |\n| Create/replace group | PUT | /policy/api/v1/infra/domains/default/groups/{id} |\n| Delete group | DELETE | /policy/api/v1/infra/domains/default/groups/{id} (first GETs `/policy/api/v1/infra/group-associations?intent_path=<group path>` for parent groups, and walks `security-policies` and `gateway-policies` with their `rules` for references; MCP also GETs the group) |\n| Group members (VMs) | GET | /policy/api/v1/infra/domains/default/groups/{id}/members/virtual-machines |\n| List VM tags | GET | /api/v1/fabric/virtual-machines?display_name={name} |\n| Apply tag | POST | /api/v1/fabric/virtual-machines?action=add_tags |\n| Remove tag | POST | /api/v1/fabric/virtual-machines?action=remove_tags |\n| Create traceflow | POST | /api/v1/traceflows |\n| Get traceflow | GET | /api/v1/traceflows/{id} |\n| Traceflow observations | GET | /api/v1/traceflows/{id}/observations |\n| Delete traceflow | DELETE | /api/v1/traceflows/{id} |\n| IDPS profiles | GET | /policy/api/v1/infra/settings/firewall/security/intrusion-services/profiles |\n| IDPS signature status | GET | /policy/api/v1/infra/settings/firewall/security/intrusion-services/signatures/status |\n| IDPS settings | GET | /policy/api/v1/infra/settings/firewall/security/intrusion-services |\n| DFW exclusion list | GET | /policy/api/v1/infra/settings/firewall/security/exclude-list?system_owned=true |\n\n## DFW Exclusion List\n\nA member on the NSX distributed-firewall exclusion list has **no DFW in its\ndatapath**. Rules that name it, groups that contain it and policies scoped to it\nall still exist, and none of them applies. Any statement that such a VM is\nmicro-segmented is wrong — and wrong in the direction that closes an\ninvestigation rather than opening one. On one real NSX 9.1.0.0200 fabric, 10 of\n12 VMs were on the list, vCenter and VCF Operations and an NSX manager among\nthem.\n\n`list_dfw_exclusions` reads it. Three contract details, checked against the\npublished NSX 9.1.0 API reference rather than recalled:\n\n- **`members` is an array of Group paths, not VM references.** The\n  `PolicyExcludeList` schema types it as strings (max 100). Naming the VMs\n  therefore means resolving each group's\n  `/members/virtual-machines`, which is what the tool does.\n- **`?system_owned=true` is required to see NSX's own exclusions.** Without it\n  only user-added members come back. The response's `scope` says which list\n  answered — `\"user\"` means system exclusions are absent, so an empty result\n  there proves nothing.\n- **The Manager API `GET /api/v1/firewall/excludelist` is removed in NSX 9.1.**\n  Its members *are* VM references, so it is the endpoint one reaches for first;\n  it appears on the 9.1.0 Removed Methods page and would 404. A regression test\n  fails if it ever appears in this package.\n\nThere is no single call for effective per-VM exclusion state\n(`?action=filter` answers one object per request, which is the per-item pattern\n踩坑 #31 forbids). The cost is therefore one GET plus one member fetch per\n*excluded group* — bounded by the exclusion list, never by the estate.\n\nWhere it surfaces:\n\n| Tool | Field | Meaning |\n|------|-------|---------|\n| `list_dfw_exclusions` | `items[]`, `scope` | The list itself, resolved to VMs |\n| `list_vm_tags` | `dfw_excluded`, `dfw_exclusion_note` | Per-VM verdict: `true` / `false` / `null` for \"could not be read\" |\n| `get_group` | `dfw_excluded` (group and each member) | Whether rules naming this group reach it |\n| `list_dfw_policies` | `exclusion_note` | Present only when something is excluded |\n\n`null` is never `false`. A lookup that failed and answered \"not excluded\" would\nbe the same confidently wrong answer about protection, arriving by a different\nroute.\n\n## NSX Version Compatibility\n\n| NSX Version | Support Level | Notes |\n|-------------|--------------|-------|\n| NSX 9.1 | Full | DFW Policy API paths unchanged. VDS 7.0+ required (N-VDS removed in NSX 9 — no impact on DFW skill). |\n| NSX 9.0 | Full | DFW Policy API paths unchanged. Bare-metal NSX agent removed (no impact on DFW skill — Policy API only). |\n| NSX 4.2.x | Full | Latest, all DFW + Security Group + Traceflow + IDS/IPS features supported |\n| NSX 4.1.x | Full | All features supported |\n| NSX 4.0.x | Full | Policy API v1 fully available |\n| NSX-T 3.2.x | Full | Policy API mature, all features work |\n| NSX-T 3.1.x | Full | DFW Policy API stable |\n| NSX-T 3.0.x | Compatible | Policy API available; some IDS/IPS endpoints introduced later |\n| NSX-T 2.5.x | Limited | Policy API available but incomplete; some tools may fail |\n| NSX-V (6.x) | Not supported | Completely different API (SOAP-based). Use legacy tools |\n\n### VCF (VMware Cloud Foundation) Compatibility\n\n| VCF Version | Bundled NSX | Support |\n|-------------|-------------|---------|\n| VCF 9.1 | NSX 9.1 | Full |\n| VCF 9.0 | NSX 9.0 | Full |\n| VCF 5.2 | NSX 4.2.x | Full |\n| VCF 5.1 | NSX 4.1.x | Full |\n| VCF 5.0 | NSX 4.0.x | Full |\n| VCF 4.5 | NSX-T 3.2.x | Full |\n| VCF 4.4 | NSX-T 3.2.x | Full |\n| VCF 4.3 | NSX-T 3.1.x | Full |\n\n**Note**: This skill uses the NSX-T Policy API only. NSX 9 changes that affect the network plane (N-VDS removal, bare-metal agent removal) do not affect DFW, Security Group, Traceflow, or IDS/IPS operations exposed by this skill.\n\nFile v1.12.0:references/cli-reference.md\n\n# VMware NSX Security CLI Reference\n\n## Global Options\n\n| Option | Short | Description |\n|--------|-------|-------------|\n| `--target` | `-t` | NSX Manager target name from config (uses `default_target` if omitted) |\n| `--config` | `-c` | Path to config file (overrides `VMWARE_NSX_SECURITY_CONFIG` env var) |\n| `--dry-run` | | Preview API call without executing (write commands only) |\n| `--help` | | Show help for any command |\n\n---\n\n## `policy` — DFW Policy Management\n\n### `policy list`\nList all DFW security policies.\n\n```bash\nvmware-nsx-security policy list [--target <name>]\n```\n\nOutput columns: ID, Display Name, Category, Seq#, Stateful, Rules\n\n### `policy get`\nGet full details of a DFW policy.\n\n```bash\nvmware-nsx-security policy get <policy-id> [--target <name>]\n```\n\n### `policy create`\nCreate a new DFW security policy.\n\n```bash\nvmware-nsx-security policy create <policy-id> \\\n  --name \"Display Name\" \\\n  [--category Ethernet|Emergency|Infrastructure|Environment|Application] \\\n  [--seq <number>] \\\n  [--description \"text\"] \\\n  [--dry-run] \\\n  [--target <name>]\n```\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `--name` | required | Human-readable policy name |\n| `--category` | Application | Policy evaluation category (validated; Ethernet evaluated first, Application last) |\n| `--seq` | 10 | Sequence number (lower = higher priority) |\n| `--description` | \"\" | Optional description |\n\n### `policy delete`\nDelete a DFW policy (requires no active rules).\n\n```bash\nvmware-nsx-security policy delete <policy-id> [--dry-run] [--target <name>]\n```\n\nPrompts for double confirmation. Fails if the policy contains rules.\n\n---\n\n## `rule` — DFW Rule Management\n\n### `rule list`\nList all rules in a policy.\n\n```bash\nvmware-nsx-security rule list <policy-id> [--target <name>]\n```\n\nOutput columns: ID, Display Name, Action, Direction, Disabled, Logged\n\n### `rule stats`\nGet packet/byte hit-count statistics for a rule.\n\n```bash\nvmware-nsx-security rule stats <policy-id> <rule-id> [--target <name>]\n```\n\nOutput fields: `packet_count`, `byte_count`, `session_count`, `hit_count`\n(summed across enforcement points), `popularity_index` (max).\n\n### `rule delete`\nDelete a DFW rule.\n\n```bash\nvmware-nsx-security rule delete <policy-id> <rule-id> [--dry-run] [--target <name>]\n```\n\nPrompts for double confirmation.\n\n---\n\n## `group` — Security Group Management\n\n### `group list`\nList all security groups.\n\n```bash\nvmware-nsx-security group list [--target <name>]\n```\n\n### `group get`\nGet group details including membership criteria and effective VM members.\n\n```bash\nvmware-nsx-security group get <group-id> [--target <name>]\n```\n\n### `group delete`\nDelete a security group (checks for DFW references first).\n\n```bash\nvmware-nsx-security group delete <group-id> [--dry-run] [--target <name>]\n```\n\nRefuses deletion if the group is a member of another group, or is\nreferenced by any DFW or gateway-firewall rule (source, destination, or\napplied-to scope) or by a policy-level scope. If the\nreference scan itself fails, deletion is aborted rather than proceeding\nblind.\n\n> Group **creation** (with tag/IP/segment criteria) is exposed via the\n> `create_group` MCP tool. The tag criterion is a Policy Condition with a\n> pipe-delimited value `\"scope|tag\"`; multiple criteria are ORed.\n\n---\n\n## `tag` — VM NSX Tag Management\n\n### `tag list`\nList NSX tags on a VM by display name.\n\n```bash\nvmware-nsx-security tag list <vm-display-name> [--target <name>]\n```\n\n### `tag apply`\nApply an NSX tag to a VM (by external ID).\n\n```bash\nvmware-nsx-security tag apply <vm-external-id> \\\n  --scope <scope> \\\n  --value <value> \\\n  [--dry-run] \\\n  [--target <name>]\n```\n\n| Option | Description |\n|--------|-------------|\n| `--scope` | Tag scope (e.g. `tier`, `env`, `owner`) |\n| `--value` | Tag value (e.g. `web`, `production`) |\n\nAdditive — existing tags on the VM are preserved. Uses\n`POST /api/v1/fabric/virtual-machines?action=add_tags` with body\n`{\"external_id\", \"tags\"}`.\n\n### `tag remove`\nRemove an NSX tag from a VM (by external ID).\n\n```bash\nvmware-nsx-security tag remove <vm-external-id> \\\n  --scope <scope> \\\n  --value <value> \\\n  [--dry-run] \\\n  [--target <name>]\n```\n\n| Option | Description |\n|--------|-------------|\n| `--scope` | Tag scope of the tag to remove |\n| `--value` | Tag value of the tag to remove |\n\nRemoves only the exact scope/value pair; other tags are preserved. May\nchange dynamic security group membership immediately — which is why this\ncommand **asks for confirmation twice**, like the other destructive commands\nhere. It takes no bypass flag, so a script that called it unattended before\nwill now wait for input; use `--dry-run` to preview. Uses\n`POST /api/v1/fabric/virtual-machines?action=remove_tags` with body\n`{\"external_id\", \"tags\"}`.\n\n---\n\n## `traceflow` — Packet Tracing\n\n### `traceflow run`\nInitiate a Traceflow and wait for results.\n\n```bash\nvmware-nsx-security traceflow run <src-lport-id> \\\n  --src-ip <ip> \\\n  --dst-ip <ip> \\\n  [--proto TCP|UDP|ICMP] \\\n  [--dst-port <port>] \\\n  [--target <name>]\n```\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `--src-ip` | required | Source IP for probe packet |\n| `--dst-ip` | required | Destination IP |\n| `--proto` | TCP | Protocol: TCP, UDP, or ICMP |\n| `--dst-port` | 80 | Destination port (TCP/UDP) |\n\nOutput: `operation_state` (`IN_PROGRESS` / `FINISHED` / `FAILED`),\n`observations` discriminated by `resource_type` (e.g.\n`TraceflowObservationForwarded`, `TraceflowObservationDroppedLogical` —\nDropped* entries carry `reason` and `acl_rule_id`), and a `dfw_hits`\nsummary of observations that matched a DFW rule.\n\n---\n\n## `idps` — IDPS Operations\n\n### `idps profiles`\nList all IDPS profiles.\n\n```bash\nvmware-nsx-security idps profiles [--target <name>]\n```\n\n### `idps status`\nGet IDPS signature status and global IDS settings.\n\n```bash\nvmware-nsx-security idps status [--target <name>]\n```\n\nOutput: `signature_status` (scalar fields of the signature bundle status\nresource — field names vary by NSX release) and `settings`\n(`auto_update`, `ids_events_to_syslog`).\n\n---\n\n## `doctor` — Environment Diagnostics\n\nRun pre-flight checks: config file, .env permissions, config parse, passwords, network reachability, NSX authentication, NSX version, MCP server import.\n\n```bash\nvmware-nsx-security doctor [--skip-auth] [--config <path>]\n```\n\n| Option | Description |\n|--------|-------------|\n| `--skip-auth` | Skip authentication tests (network check only) |\n| `--config` | Override config file path |\n\n---\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `VMWARE_NSX_SECURITY_CONFIG` | Path to config YAML file |\n| `VMWARE_NSX_SECURITY_<TARGET>_PASSWORD` | Password for target (hyphens → underscores, uppercase) |\n\n**Password examples**:\n- Target `nsx-prod` → `VMWARE_NSX_SECURITY_NSX_PROD_PASSWORD`\n- Target `nsx-lab` → `VMWARE_NSX_SECURITY_NSX_LAB_PASSWORD`\n\nFile v1.12.0:references/setup-guide.md\n\n# VMware NSX Security — Setup Guide\n\n## Prerequisites\n\n- NSX Manager 3.x or 4.x (NSX-T)\n- An NSX admin account with DFW read/write permissions\n- Python 3.10+ and `uv` installed\n\n## 1. Install\n\n```bash\nuv tool install vmware-nsx-security==1.12.0\n```\n\nVerify:\n```bash\nvmware-nsx-security --help\n```\n\n## 2. Create Config Directory\n\n```bash\nmkdir -p ~/.vmware-nsx-security\n```\n\n## 3. Create Config File\n\nCopy the example and edit:\n\n```bash\n# From the package source directory\ncp config.example.yaml ~/.vmware-nsx-security/config.yaml\n```\n\nOr create manually:\n\n```yaml\n# ~/.vmware-nsx-security/config.yaml\ntargets:\n  nsx-prod:\n    host: nsx-manager.example.com\n    username: admin\n    port: 443\n    verify_ssl: true\n    environment: production   # Which environment this is — see below\n  nsx-lab:\n    host: 10.0.0.50\n    username: admin\n    port: 443\n    verify_ssl: false   # Allow self-signed cert in lab\n    environment: lab\n\ndefault_target: nsx-prod\n```\n\n**`environment` (optional label)**: policy scopes its rules by this value, so an environment-scoped `deny` rule in `~/.vmware/rules.yaml` can match on it — for example, to freeze state-changing writes on `production`. Any label you like works (`production`, `staging`, `lab`, `dc2-prod`); the target's *name* is not used for it.\n\nA target with no label is simply not matched by such a rule. Read-only operations are never affected either way. Run `vmware-audit policy` to see the rules currently in force.\n\n## 4. Set Passwords\n\nPasswords are **never** stored in `config.yaml`. Use environment variables or a `.env` file:\n\n```bash\n# Create .env file\ncat > ~/.vmware-nsx-security/.env << 'EOF'\nVMWARE_NSX_SECURITY_NSX_PROD_PASSWORD=your_prod_password\nVMWARE_NSX_SECURITY_NSX_LAB_PASSWORD=your_lab_password\nEOF\n\n# Secure the file — IMPORTANT\nchmod 600 ~/.vmware-nsx-security/.env\n```\n\n**Password variable naming convention**: `VMWARE_NSX_SECURITY_<TARGET>_PASSWORD`\nwhere `<TARGET>` is the target name uppercased with hyphens → underscores.\n\n## 5. Verify Setup\n\n```bash\nvmware-nsx-security doctor\n```\n\nAll checks should show PASS:\n- Config file\n- .env permissions (owner-only 600)\n- Config parse (N targets configured)\n- Password (set for each target)\n- Network (TCP reachable on port 443)\n- NSX auth (session created)\n- NSX version (vX.Y.Z)\n- MCP server import\n\n## 6. Configure MCP Server\n\n### Claude Code\n\nAdd to `~/.claude.json` (or `.claude.json` in your project):\n\n```json\n{\n  \"mcpServers\": {\n    \"vmware-nsx-security\": {\n      \"command\": \"vmware-nsx-security\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"VMWARE_NSX_SECURITY_CONFIG\": \"~/.vmware-nsx-security/config.yaml\"\n      }\n    }\n  }\n}\n```\n\n### Cursor\n\nIn Cursor Settings → MCP Servers:\n\n```json\n{\n  \"vmware-nsx-security\": {\n    \"command\": \"vmware-nsx-security\",\n    \"args\": [\"mcp\"],\n    \"env\": {\n      \"VMWARE_NSX_SECURITY_CONFIG\": \"${HOME}/.vmware-nsx-security/config.yaml\"\n    }\n  }\n}\n```\n\n### Goose\n\n```json\n{\n  \"mcpServers\": {\n    \"vmware-nsx-security\": {\n      \"command\": \"vmware-nsx-security\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"VMWARE_NSX_SECURITY_CONFIG\": \"~/.vmware-nsx-security/config.yaml\"\n      }\n    }\n  }\n}\n```\n\n> v1.5.15+ recommends the single-command form `vmware-nsx-security mcp`. Pre-1.5.15 used\n> `uvx --from vmware-nsx-security vmware-nsx-security-mcp`, which still works but re-resolves <!-- install-pin: historical -->\n> from PyPI on each launch and breaks behind corporate TLS proxies. The legacy\n> `vmware-nsx-security-mcp` entry point is also kept for backward compatibility.\n\n## 7. Docker (Optional)\n\nBuild and run as a container:\n\n```bash\ndocker-compose up --build\n```\n\nMount your config:\n```yaml\n# docker-compose.yml already mounts ~/.vmware-nsx-security:/root/.vmware-nsx-security:ro\n```\n\n## Companion Skill Setup\n\nFor full NSX coverage, also install:\n\n```bash\n# NSX networking: segments, gateways, NAT, routing\nuv tool install vmware-nsx-mgmt\n\n# vSphere monitoring\nuv tool install vmware-monitor\n```\n\nConfigure each with its own config directory:\n- NSX networking: `~/.vmware-nsx/config.yaml`\n- NSX security: `~/.vmware-nsx-security/config.yaml`\n- Monitor: `~/.vmware-monitor/config.yaml`\n\nBoth `vmware-nsx` and `vmware-nsx-security` can point to the same NSX Manager hosts — the config files are separate because the password env vars differ.\n\n### Password obfuscation at rest\n\nOn first load, any plaintext `*_PASSWORD` value in `.env` is automatically\nrewritten to a grep-safe `b64:<encoded>` form and decoded transparently at\nruntime, so a casual `grep` of the file no longer reveals the password. Values\nare read and written through python-dotenv's own parser, so the stored secret\nnever drifts from what you configured (quotes, inline comments, and trailing\nwhitespace are handled correctly).\n\n> **This is obfuscation, not encryption.** Anyone who can read the file can\n> still decode it. For real secrecy at rest, do not store the password in `.env`\n> at all — inject it from a secret manager (HashiCorp Vault, CyberArk, AWS\n> Secrets Manager, or a Kubernetes Secret) into the `*_PASSWORD` environment\n> variable at process start. The code reads the env var either way.\n\n## Running the Agent Read-Only\n\nTo run the agent read-only, give it a read-only NSX service account (RBAC) — writes are then refused by NSX itself, on every surface, which no env var or config switch could guarantee.\n\n## Security Notes\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"NSX\" are trademarks of Broadcom.\n\n- **Source Code**: Fully open source at [github.com/vmware-skills/VMware-NSX-Security](https://github.com/vmware-skills/VMware-NSX-Security) (MIT). The `uv` installer fetches the `vmware-nsx-security` package from PyPI, which is built from this GitHub repository. We recommend reviewing the source code and commit history before deploying in production.\n- `config.yaml` should be readable only by your user: `chmod 600 ~/.vmware-nsx-security/config.yaml`\n- `.env` must be `chmod 600` — the doctor check warns if it is too permissive\n- Use a dedicated read/write NSX account for security operations, not the global `admin` superuser\n- Audit logs are written to `~/.vmware/audit.db` (SQLite WAL mode, via vmware-policy)\n- The MCP server uses stdio transport — it never opens a network port; it is started on-demand by your AI agent\n\nFile v1.12.0:skill-card.md\n\n## Description:\n\nUse this skill to manage VMware NSX security for distributed firewall policies and rules, security groups, VM tags, Traceflow diagnostics, and IDPS profile/status tasks.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, platform engineers, and security operators use this skill to inspect and administer VMware NSX/vDefend security controls, including DFW policies, security groups, tags, Traceflow diagnostics, and IDPS status. It is suited to controlled infrastructure operations where proposed writes and destructive actions are reviewed before execution.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can administer NSX security policy, including firewall-related write operations.\n\nMitigation: Install it only for agents intended to manage NSX security policy and use a dedicated least-privilege NSX account.\n\nRisk: Persistent .env credentials can expose NSX access if the host or file permissions are mishandled.\n\nMitigation: Prefer injected secrets or a secret manager for production, and keep any local credential files tightly permissioned.\n\nRisk: Deletes and tag changes can alter firewall enforcement or group membership.\n\nMitigation: Keep audit logging enabled and review previews before confirming deletes or tag changes.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/vmware-nsx-security)\n- [Publisher profile](https://clawhub.ai/user/zw008)\n- [Project homepage](https://github.com/vmware-skills/VMware-NSX-Security)\n- [Setup Guide](artifact/references/setup-guide.md)\n- [CLI Reference](artifact/references/cli-reference.md)\n- [Capabilities Reference](artifact/references/capabilities.md)\n- [Agent Guardrails](artifact/references/agent-guardrails.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown with inline shell commands and structured operational guidance]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May produce NSX security operation plans, CLI commands, configuration snippets, MCP tool-use guidance, and reviewable previews for destructive changes.]\n\n## Skill Version(s):\n\n1.12.0 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.12.0:evals/evals.json\n\n{\n  \"skill_name\": \"vmware-nsx-security\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"prompt\": \"Create a firewall rule to block all traffic from the dev segment to the production database VMs\",\n      \"expected_output\": \"DFW rule created with correct source/destination\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses create_dfw_policy or creates within existing policy\",\n        \"Uses create_dfw_rule with correct source and destination groups\",\n        \"Sets action to DROP or REJECT\"\n      ]\n    },\n    {\n      \"id\": 2,\n      \"prompt\": \"Run a traceflow from VM web-01 to VM db-01 on port 3306 to verify MySQL connectivity\",\n      \"expected_output\": \"Traceflow result showing path and allow/deny\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses run_traceflow with correct source, destination, and port\",\n        \"Uses get_traceflow_result to show the path\",\n        \"Reports whether traffic is allowed or blocked\"\n      ]\n    },\n    {\n      \"id\": 3,\n      \"prompt\": \"Create a security group for all web servers and tag VMs web-01, web-02, web-03\",\n      \"expected_output\": \"Security group created, VMs tagged\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses create_group for the security group\",\n        \"Uses apply_vm_tag for each VM\",\n        \"Group membership based on tags\"\n      ]\n    }\n  ]\n}\n\nArchive v1.11.1: 8 files, 26455 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (8999b), references/capabilities.md (13874b), references/cli-reference.md (6886b), references/setup-guide.md (6433b), skill-card.md (2516b), SKILL.md (20250b), _meta.json (139b)\n\nFile v1.11.1:SKILL.md\n\n---\nname: vmware-nsx-security\ndescription: >\n  Use this skill whenever the user needs to manage VMware NSX security (rebranded VMware vDefend in VCF 9) — distributed firewall (DFW) policies, security groups, microsegmentation, and IDS/IPS.\n  Directly handles: create/manage DFW policies and rules, security groups, VM tags, network traceflow diagnostics, IDPS profiles and status.\n  Always use this skill for \"create firewall rule\", \"set up microsegmentation\", \"add VM to security group\", \"run traceflow\", \"check IDS status\", \"vDefend firewall rule\", or any NSX security / vDefend / DFW task.\n  Do NOT use for NSX networking operations like segments, gateways, NAT, or routing (use vmware-nsx), or VM lifecycle (use vmware-aiops).\n  For load balancing/AVI/AKO use vmware-avi.\ninstaller:\n  kind: uv\n  package: vmware-nsx-security\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-nsx-security\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_NSX_SECURITY_CONFIG\",\"VMWARE_NSX_SECURITY_<TARGET>_PASSWORD\",\"VMWARE_NSX_SECURITY_<TARGET>_USERNAME\",\"VMWARE_AUDIT_APPROVED_BY\"],\"bins\":[\"vmware-policy\"]},\"homepage\":\"https://github.com/vmware-skills/VMware-NSX-Security\",\"emoji\":\"🔒\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  vmware-policy auto-installed as Python dependency (provides @vmware_tool decorator and audit logging). All write operations audited to ~/.vmware/audit.db.\n  Credentials: Each NSX Manager target requires a per-target password env var in ~/.vmware-nsx-security/.env following the pattern VMWARE_NSX_SECURITY_<TARGET_NAME_UPPER>_PASSWORD. Passwords are never logged or echoed.\n  Destructive operations: DFW policy delete checks for active rules, security group delete checks for references. IDS/IPS config changes require double confirmation. Traceflow is read-only.\n  No webhooks, no outbound network calls, no guest operations. Local only: stdio MCP + NSX Policy API (HTTPS 443).\n  Transitive dependencies: Only vmware-policy (audit/policy). No post-install scripts or background services.\n---\n\n# VMware NSX Security\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"NSX\" are trademarks of Broadcom. Source code is publicly auditable at [github.com/vmware-skills/VMware-NSX-Security](https://github.com/vmware-skills/VMware-NSX-Security) under the MIT license.\n\nVMware NSX DFW microsegmentation and security — 22 MCP tools for distributed firewall, security groups, VM tags, the DFW exclusion list, Traceflow, and IDPS.\n\n> Domain-focused security skill for NSX-T / NSX 4.x Policy API.\n> **Companion skills**: [vmware-nsx](https://github.com/vmware-skills/VMware-NSX) (networking), [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (VM lifecycle), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only monitoring), [vmware-avi](https://github.com/vmware-skills/VMware-AVI) (AVI/ALB/AKO), [vmware-harden](https://github.com/vmware-skills/VMware-Harden) (compliance baselines).\n> | [vmware-pilot](../vmware-pilot/SKILL.md) (workflow orchestration) | [vmware-policy](../vmware-policy/SKILL.md) (audit/policy)\n\n## What This Skill Does\n\n| Category | Tools | Count |\n|----------|-------|:-----:|\n| **DFW Policy** | list, get, create, update, delete, list rules | 6 |\n| **DFW Rules** | create, update, delete, get stats | 4 |\n| **Security Groups** | list, get, create, delete | 4 |\n| **VM Tags** | list VM tags, apply tag, remove tag | 3 |\n| **Traceflow** | run trace, get result | 2 |\n| **IDPS** | list profiles, get status | 2 |\n| **DFW Exclusions** | list excluded members | 1 |\n\n**Total**: 22 tools (11 read-only + 11 write)\n\n## Quick Install\n\n```bash\nuv tool install vmware-nsx-security==1.11.1\nvmware-nsx-security init      # guided setup: writes config + .env (chmod 600, password grep-safe), then verifies\nvmware-nsx-security doctor\n```\n\n## When to Use This Skill\n\n- List, create, or modify DFW security policies and rules\n- Create security groups based on VM tags, IP ranges, or segment membership\n- Apply or list NSX tags on virtual machines\n- Run Traceflow to trace a packet path and diagnose drop reasons\n- Check IDPS profile configuration, signature status, and global IDS settings\n- Implement zero-trust microsegmentation between application tiers\n- Check the DFW exclusion list — which VMs no distributed-firewall rule reaches\n\n**Use companion skills for**:\n- NSX segments, gateways, NAT, routing, IPAM → `vmware-nsx`\n- VM lifecycle, deployment, guest ops → `vmware-aiops`\n- vSphere inventory, health, alarms, events → `vmware-monitor`\n- Storage: iSCSI, vSAN, datastores → `vmware-storage`\n- Tanzu Kubernetes → `vmware-vks`\n- Load balancing, AVI/ALB, AKO, Ingress → `vmware-avi`\n\n## Related Skills — Skill Routing\n\n| User Intent | Recommended Skill |\n|-------------|-------------------|\n| NSX security: DFW rules, security groups, IDS/IPS | **vmware-nsx-security** ← this skill |\n| NSX networking: segments, gateways, NAT, routing | **vmware-nsx** |\n| Read-only vSphere monitoring, alarms, events | **vmware-monitor** |\n| VM lifecycle, deployment, guest ops | **vmware-aiops** |\n| Storage: iSCSI, vSAN, datastores | **vmware-storage** |\n| Tanzu Kubernetes | **vmware-vks** |\n| Multi-step workflows with approval | **vmware-pilot** |\n| Compliance baselines (CIS / 等保 / PCI-DSS), drift detection, LLM remediation advisor | **vmware-harden** (`uv tool install vmware-harden`) |\n| Load balancer, AVI, ALB, AKO, Ingress | **vmware-avi** (`uv tool install vmware-avi`) |\n| Audit log query | **vmware-policy** (`vmware-audit` CLI) |\n\n## Common Workflows\n\n### Implement App-Tier Microsegmentation\n\n**Pre-flight (judgment — DFW changes can lock everyone out)**:\n- **Default-allow first**: the very first rule in any new policy must be ALLOW for management traffic (DNS, NTP, vCenter, SSH from jumphost). Without it, the moment you add a default-deny you blackhole your own access.\n- Tag inventory: confirm the VMs you intend to protect actually carry the tag (`tag list <vm>`). A group based on a non-existent tag matches zero VMs — the policy will appear \"applied\" but enforce nothing.\n- Category choice: `Application` for app-tier microseg (rules evaluated late, after Infrastructure rules pass through). Using `Emergency` for routine rules will starve real incident-response capacity.\n- Stateless? Default to stateful — NSX DFW is stateful and almost no rule should be stateless. Stateless = both directions must be explicitly allowed.\n- Always start with **logging enabled** on new rules; disable later once verified. Silent drops are the worst kind of bug.\n\n**Steps**:\n1. Tag the VMs first (see workflow below) — empty groups = no enforcement\n2. Create groups via the `create_group` MCP tool with `tag_scope`/`tag_value` (the tag condition is matched as `\"scope|tag\"`, e.g. `tier|web`; note multiple criteria types — tag/IP/segment — are ORed, not ANDed)\n3. `policy create app-microseg --category Application`\n4. Add rules in order: ALLOW management → ALLOW intra-tier → ALLOW web→app on app-port → DROP any-any with logging\n5. Verify with traceflow (see below) **before** enabling default-deny\n\n### Answer \"is this VM protected by the DFW?\"\n\nNever from the policy and rule listings alone. A VM on the **DFW exclusion list**\nhas no distributed firewall in its datapath: the rules that name it exist and\nnone of them applies. On a VCF estate the management VMs (vCenter, VCF\nOperations, NSX managers) are commonly excluded — one real 9.1 fabric had 10 of\n12 hosts on that list.\n\n1. `list_dfw_exclusions` — the whole list, resolved to the VMs in each group.\n   Check `scope`: `\"user\"` means system-owned exclusions are **not** in the\n   answer, so an empty list there is not proof of anything.\n2. `list_vm_tags <vm>` — `dfw_excluded` is the per-VM verdict. `true` means no\n   rule reaches it; `null` means the list could not be read, which is **not**\n   `false`, so say \"unknown\" rather than \"protected\".\n3. Only then read `list_dfw_policies` / `list_dfw_rules` for what is enforced on\n   the VMs that are not excluded. That listing carries `exclusion_note` whenever\n   anything is on the list.\n\n### Apply NSX Tags to VMs\n\n**Judgment**: tags drive group membership which drives DFW enforcement. A misspelled tag silently excludes a VM from protection. Always re-list after applying.\n\n1. `tag list my-web-vm-01` → record the VM external ID, also see what tags already exist (avoid duplicates / typo collisions)\n2. `tag apply <vm-external-id> --scope tier --value web`\n3. **Verify**: `tag list my-web-vm-01` again → confirm the new tag is present AND no unexpected ones\n\n### Trace a Packet with Traceflow\n\n**Judgment**: traceflow is your verification mechanism for any DFW change. Run it **before** enabling deny rules and **after** every rule modification. Don't trust \"looks right in the UI.\"\n\n1. Get source VM's logical port ID via `vmware-nsx troubleshoot vm-segment`\n2. `traceflow run <lport-id> --src-ip <src> --dst-ip <dst> --proto TCP --dst-port <port>`\n3. Inspect the DFW hit chain: which rule matched, ALLOW or DROP, and at which transport node\n4. **Common failure**: rule matches at category Application but is shadowed by an earlier DROP at category Environment — read the trace top-to-bottom, not just the final verdict\n\n### Check DFW Policy Hit Counts\n\n```bash\nvmware-nsx-security policy list\nvmware-nsx-security rule list <policy-id>\nvmware-nsx-security rule stats <policy-id> <rule-id>\n```\n\n### Multi-Target Operations\n\nAll commands accept `--target <name>` to operate against a specific NSX Manager:\n\n```bash\n# Default target\nvmware-nsx-security policy list\n\n# Specific target\nvmware-nsx-security policy list --target nsx-prod\nvmware-nsx-security group list --target nsx-lab\n```\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models (Ollama, Qwen) | **CLI** | ~2K tokens vs ~8K for MCP |\n| Cloud models (Claude, GPT-4o) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | Type-safe parameters, structured output |\n\nRunning with local or small models? See [`references/agent-guardrails.md`](references/agent-guardrails.md) for explicit operating rules.\n\n## MCP Tools (22 — 11 read, 11 write)\n\nAll MCP tools accept an optional `target` parameter.\n\n`list_dfw_policies`, `list_dfw_rules`, `list_groups` and `list_idps_profiles` return the family\nlist envelope — `{items, returned, limit, total, truncated, hint}` — rather than a bare array.\nRead the rows from `items` and check `truncated` before concluding a listing is complete; a\n50-row default page looks identical to a whole estate without it. `total` is stated only where\nthe scan proved it: it is the real count on an unfiltered listing that stayed under the\n1000-item `get_all` cap, and `null` for name-filtered listings, capped scans, and\n`list_dfw_rules` (whose fetch is bounded to the requested window). `truncated` says `items` is not the whole\ncollection; it is still true on the last page of a walk, so page with `next_offset` and stop\nwhen it is `null`, never on `truncated`. The `hint` says which of the two you are looking at.\nErrors return\n`{error, hint}` (a dict, not a one-element list).\n\n| Category | Tool | Type | Description |\n|----------|------|:----:|-------------|\n| DFW Exclusions | `list_dfw_exclusions` | Read | List the DFW exclusion list — members no DFW rule reaches. Read this before calling any VM micro-segmented |\n| DFW Policy | `list_dfw_policies` | Read | List all DFW security policies with category, sequence, and rule count |\n| | `get_dfw_policy` | Read | Get policy details: category, stateful, locked, scope, tags |\n| | `create_dfw_policy` | Write | Create a new DFW policy with category and sequence number |\n| | `update_dfw_policy` | Write | Partial update: display_name, description, sequence_number, stateful |\n| | `delete_dfw_policy` | Write | Delete policy — refuses if active rules exist |\n| | `list_dfw_rules` | Read | List rules in a policy: action, sources, destinations, services |\n| DFW Rules | `create_dfw_rule` | Write | Create rule with sources/destinations/services/action/scope |\n| | `update_dfw_rule` | Write | Partial update rule fields |\n| | `delete_dfw_rule` | Write | Delete a rule from a policy |\n| | `get_dfw_rule_stats` | Read | Get packet/byte/session/hit counts and popularity_index for a rule |\n| Security Groups | `list_groups` | Read | List all security groups with expression count |\n| | `get_group` | Read | Get group details: expression criteria + up to 50 effective VM members |\n| | `create_group` | Write | Create group with tag/IP/segment membership criteria (tag matched as \"scope\\|tag\"; multiple criteria ORed) |\n| | `delete_group` | Write | Delete group — refuses if referenced by DFW rules/scopes, or if the reference scan fails |\n| VM Tags | `list_vm_tags` | Read | List NSX tags on a VM by display name |\n| | `apply_vm_tag` | Write | Apply a scope/value tag to a VM (additive, preserves existing tags) |\n| | `remove_vm_tag` | Write | Remove a scope/value tag from a VM (other tags preserved; may change dynamic group membership) |\n| Traceflow | `run_traceflow` | Write | Inject probe packet; returns operation_state + hop-by-hop observations (by resource_type) + dfw_hits |\n| | `get_traceflow_result` | Read | Check operation_state/observations of an existing traceflow |\n| IDPS | `list_idps_profiles` | Read | List IDPS profiles with severity and filter criteria |\n| | `get_idps_status` | Read | Get IDPS signature status + global IDS settings (auto_update, syslog export) |\n\n## CLI Quick Reference\n\n```bash\n# DFW Policy\nvmware-nsx-security policy list [--target <name>]\nvmware-nsx-security policy get <policy-id>\nvmware-nsx-security policy create <id> --name \"Display Name\" --category Application [--dry-run]\nvmware-nsx-security policy delete <id> [--dry-run]\n\n# DFW Rules\nvmware-nsx-security rule list <policy-id>\nvmware-nsx-security rule stats <policy-id> <rule-id>\nvmware-nsx-security rule delete <policy-id> <rule-id> [--dry-run]\n\n# Security Groups\nvmware-nsx-security group list\nvmware-nsx-security group get <group-id>\nvmware-ns\n\nArchive v1.11.0: 8 files, 26461 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (8999b), references/capabilities.md (13874b), references/cli-reference.md (6886b), references/setup-guide.md (6433b), skill-card.md (2433b), SKILL.md (20250b), _meta.json (139b)\n\nArchive v1.10.0: 8 files, 26461 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (8999b), references/capabilities.md (13874b), references/cli-reference.md (6886b), references/setup-guide.md (6392b), skill-card.md (2677b), SKILL.md (20353b), _meta.json (139b)\n\nArchive v1.9.2: 8 files, 26354 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (8999b), references/capabilities.md (13874b), references/cli-reference.md (6659b), references/setup-guide.md (6392b), skill-card.md (2615b), SKILL.md (20353b), _meta.json (138b)\n\nArchive v1.9.1: 8 files, 26287 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (8999b), references/capabilities.md (13874b), references/cli-reference.md (6659b), references/setup-guide.md (6392b), skill-card.md (2502b), SKILL.md (20353b), _meta.json (138b)\n\nArchive v1.9.0: 8 files, 26332 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (8999b), references/capabilities.md (13874b), references/cli-reference.md (6659b), references/setup-guide.md (6392b), skill-card.md (2660b), SKILL.md (20353b), _meta.json (138b)\n\nArchive v1.8.12: 8 files, 24477 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (8950b), references/capabilities.md (11061b), references/cli-reference.md (6659b), references/setup-guide.md (6392b), skill-card.md (2495b), SKILL.md (18901b), _meta.json (139b)\n\nArchive v1.8.11: 8 files, 24490 bytes\n\nFiles: evals/evals.json (1326b), references/agent-guardrails.md (8950b), references/capabilities.md (11061b), references/cli-reference.md (6659b), references/setup-guide.md (6392b), skill-card.md (2502b), SKILL.md (18901b), _meta.json (139b)","readmeExcerpt":"Skill: vmware-nsx-security Owner: zw008 Summary: Use this skill whenever the user needs to manage VMware NSX security (rebranded VMware vDefend in VCF 9) — distributed firewall (DFW) policies, security groups, microsegmentation, and IDS/IPS. Directly handles: create/manage DFW policies and rules, security groups, VM tags, network traceflow diagnostics, IDPS profiles and status. Always use this skill for \"create firew","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"uv tool install vmware-nsx-security==1.13.0\nvmware-nsx-security init      # guided setup: writes config + .env (chmod 600, password grep-safe), then verifies\nvmware-nsx-security doctor"},{"language":"bash","snippet":"vmware-nsx-security policy list\nvmware-nsx-security rule list <policy-id>\nvmware-nsx-security rule stats <policy-id> <rule-id>"},{"language":"bash","snippet":"# Default target\nvmware-nsx-security policy list\n\n# Specific target\nvmware-nsx-security policy list --target nsx-prod\nvmware-nsx-security group list --target nsx-lab"},{"language":"bash","snippet":"# DFW Policy\nvmware-nsx-security policy list [--target <name>]\nvmware-nsx-security policy get <policy-id>\nvmware-nsx-security policy create <id> --name \"Display Name\" --category Application [--dry-run]\nvmware-nsx-security policy delete <id> [--dry-run]\n\n# DFW Rules\nvmware-nsx-security rule list <policy-id>\nvmware-nsx-security rule stats <policy-id> <rule-id>\nvmware-nsx-security rule delete <policy-id> <rule-id> [--dry-run]\n\n# Security Groups\nvmware-nsx-security group list\nvmware-nsx-security group get <group-id>\nvmware-nsx-security group delete <group-id> [--dry-run]\n\n# Tags\nvmware-nsx-security tag list <vm-display-name>\nvmware-nsx-security tag apply <vm-external-id> --scope env --value production [--dry-run]\nvmware-nsx-security tag remove <vm-external-id> --scope env --value production [--dry-run]\n\n# Traceflow\nvmware-nsx-security traceflow run <lport-id> --src-ip &lt;src-ip&gt; --dst-ip &lt;dst-ip&gt;\n\n# IDPS\nvmware-nsx-security idps profiles\nvmware-nsx-security idps status\n\n# Diagnostics\nvmware-nsx-security doctor [--skip-auth]"},{"language":"bash","snippet":"uv tool install vmware-nsx-security==1.13.0\nmkdir -p ~/.vmware-nsx-security\ncp config.example.yaml ~/.vmware-nsx-security/config.yaml\n# Edit config.yaml with your NSX Manager targets\n\n# Add to ~/.vmware-nsx-security/.env (create if missing, chmod 600):\n# VMWARE_NSX_SECURITY_NSX_PROD_PASSWORD=<your-password>\nchmod 600 ~/.vmware-nsx-security/.env\n\nvmware-nsx-security doctor"},{"language":"text","snippet":"User (natural language)\n  |\nAI Agent (Claude Code / Goose / Cursor)\n  | reads SKILL.md\nvmware-nsx-security CLI or MCP server (stdio transport)\n  | NSX Policy API (REST/JSON over HTTPS)\nNSX Manager\n  |\nDFW Policies / Rules / Security Groups / Tags / IDPS"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: vmware-nsx-security\ndescription: >\n  Use this skill whenever the user needs to manage VMware NSX security (rebranded VMware vDefend in VCF 9) — distributed firewall (DFW) policies, security groups, microsegmentation, and IDS/IPS.\n  Directly handles: create/manage DFW policies and rules, security groups, VM tags, network traceflow diagnostics, IDPS profiles and status.\n  Always use this skill for \"create firewall rule\", \"set up microsegmentation\", \"add VM to security group\", \"run traceflow\", \"check IDS status\", \"vDefend firewall rule\", or any NSX security / vDefend / DFW task.\n  Do NOT use for NSX networking operations like segments, gateways, NAT, or routing (use vmware-nsx), or VM lifecycle (use vmware-aiops).\n  For load balancing/AVI/AKO use vmware-avi.\ninstaller:\n  kind: uv\n  package: vmware-nsx-security\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-nsx-security\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_NSX_SECURITY_CONFIG\",\"VMWARE_NSX_SECURITY_<TARGET>_PASSWORD\",\"VMWARE_NSX_SECURITY_<TARGET>_USERNAME\",\"VMWARE_AUDIT_APPROVED_BY\"],\"bins\":[\"vmware-policy\"]},\"homepage\":\"https://github.com/vmware-skills/VMware-NSX-Security\",\"emoji\":\"🔒\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  vmware-policy auto-installed as Python dependency (provides @vmware_tool decorator and audit logging). All write operations audited to ~/.vmware/audit.db.\n  Credentials: Each NSX Manager target requires a per-target password env var in ~/.vmware-nsx-security/.env following the pattern VMWARE_NSX_SECURITY_<TARGET_NAME_UPPER>_PASSWORD. Passwords are never logged or echoed.\n  Destructive operations: DFW policy delete checks for active rules, security group delete checks for references. The three MCP delete tools preview by default — without confirm=True they return the blast radius and change nothing, and confirm=True is refused while a blocker remains or a read failed. IDS/IPS config changes require double confirmation. Traceflow is read-only.\n  No webhooks, no outbound network calls, no guest operations. Local only: stdio MCP + NSX Policy API (HTTPS 443).\n  Transitive dependencies: Only vmware-policy (audit/policy). No post-install scripts or background services.\n---\n\n# VMware NSX Security\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"NSX\" are trademarks of Broadcom. Source code is publicly auditable at [github.com/vmware-skills/VMware-NSX-Security](https://github.com/vmware-skills/VMware-NSX-Security) under the MIT license.\n\nVMware NSX DFW microsegmentation and security — 22 MCP tools for distributed firewall, security groups, VM tags, the DFW exclusion list, Traceflow, and IDPS.\n\n> Domain-focused security skill for NSX-T / NSX 4.x Policy API.\n> **Companion skills**: [vmware-nsx](https://github.com/vmware-skills/VMware-NSX) (networking), [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (VM lifecyc"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-nsx-security\",\n  \"version\": \"1.13.0\",\n  \"publishedAt\": 1789915933991\n}"},{"path":"references/agent-guardrails.md","content":"# Operating vmware-nsx-security with a local / small model\n\nClaude-class models drive this skill without special instruction. Smaller and\nlocally-hosted models — Llama 3.3 70B, Qwen, Mistral, and similar, served\nthrough Goose, Ollama, or OpenShift AI — need explicit operating rules to call\ntools reliably.\n\nThis page exists because an operator wrote those rules by hand first. The\nguardrails below are adapted, with thanks, from the working configuration\n[@juanpf-ha](https://github.com/juanpf-ha) developed while running\nvmware-monitor and vmware-aria against a production vSphere estate with Llama\n3.3 70B FP8 on an on-prem H100\n([VMware-AIops#31](https://github.com/vmware-skills/VMware-AIops/issues/31)). The\ncross-skill rules are identical across this family; the parts below marked\nvmware-nsx-security are specific to this skill.\n\nvmware-nsx-security exposes 22 MCP tools, 11 of which change state. This is a\nfirewall: a wrong rule does not raise an error, it silently permits or blocks\ntraffic, and nobody finds out until something breaks or nothing does.\n\n> **Disclaimer**: This is a community-maintained open-source project and is\n> **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom\n> Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom.\n\n---\n\n## First: the rules you no longer need to write\n\nSeveral guardrails from the original configuration are now enforced by the\nskill itself. Prompt instructions are advisory — a model can ignore them.\nThese are structural, so it cannot.\n\n| Guardrail you would otherwise prompt for | Now enforced by |\n|---|---|\n| \"Check whether a group is used anywhere before deleting it\" | **`delete_group` scans** DFW and gateway-firewall rule sources, destinations, applied-to scope and policy scope, plus parent groups, and refuses when referenced. It also refuses when the scan itself fails, rather than assuming the group is unused. |\n| \"Do not delete a policy that still has rules in it\" | **`delete_dfw_policy` refuses** while active rules exist. |\n| \"Show me what a delete would remove before it happens\" | **The three delete tools preview by default.** Without `confirm=True` they return `blast_radius` and delete nothing; `confirm=True` is refused while a blocker remains or a read failed. Pass it only after the user has seen the preview. |\n| \"Use explicit limits for queries that may return large amounts of data\" | **The list envelope.** `list_dfw_policies`, `list_dfw_rules`, `list_groups` and `list_idps_profiles` return `{items, returned, limit, total, truncated, hint}`, so the model reads truncation instead of guessing at it. A 50-row default page and a whole estate look identical without it. |\n| \"If a listing came back empty, say so rather than claiming the call failed\" | Same envelope. Empty `items` with `truncated: false` means checked-and-none — a stated result, not a silence the model has to interpret. Note `total` is `null` for name-filtered and capped listings; `truncated: true` means `items` is not"},{"path":"references/capabilities.md","content":"# VMware NSX Security — Capabilities Reference\n\n## Automation Level Reference\n\nEach operation is classified by autonomy level per the Enterprise Harness Engineering framework:\n\n| Level | Meaning | Agent autonomy | Examples in this skill |\n|:-:|---|---|---|\n| **L1** | Read-only, raw data | Always auto-run | `list_dfw_policies`, `get_dfw_policy`, `list_dfw_rules`, `get_dfw_rule_stats`, `list_groups`, `get_group`, `list_vm_tags`, `get_traceflow_result`, `list_idps_profiles`, `get_idps_status` |\n| **L2** | Read + analysis / recommendation | Always auto-run | DFW rule conflict detection, shadowed-rule analysis, security group reference graph, traceflow path interpretation |\n| **L3** | Single write — user must approve | Only after explicit confirmation; destructive CLI ops require double-confirm + `--dry-run`; the three MCP deletes preview by default and act only with `confirm=True` | `create_dfw_policy`, `create_dfw_rule`, `delete_dfw_rule`, `create_group`, `delete_group`, `apply_vm_tag`/`remove_vm_tag`, `run_traceflow` (injects a synthetic packet) |\n| **L4** | Multi-step plan / apply workflow | Plan generation auto; apply gated by user approval | *(roadmap — staged microsegmentation rollouts, emergency-block playbooks)* |\n| **L5** | Auto-remediation from learned pattern | Pattern library only; requires `risk:low` + `reversible:true` + `repeatable:true` | *(roadmap — candidates: orphaned-SG cleanup, expired temp-block rule removal)* |\n\n**Notes**:\n- L1/L2 tools are always safe for agents to call without confirmation.\n- **List envelope**: `list_dfw_policies`, `list_dfw_rules`, `list_groups` and `list_idps_profiles` return `{items, returned, limit, total, truncated, hint}` instead of a bare array, so an agent can tell a complete answer from a first page rather than inferring it (VMware-AIops issue #31). `total` is reported only where the scan proved it — the real count on an unfiltered listing under the 1000-item `get_all` cap; `null` for name-filtered listings (the Search API returns matches, not a countable set), for scans that stopped at the cap, and for `list_dfw_rules` (bounded to `offset + limit` by design). Page with the `next_offset` extra — pass it back as `offset` and stop when it is `null`. Never loop on `truncated`: it answers \"is `items` the whole collection?\", which is still `true` on the last page of a walk. The `hint` distinguishes them — mid-walk it names the next offset; on the last page it says there is no next page; past the end it says so and points back to offset 0. It never advises raising a limit that cannot return another row.\n- **`rule_count` on `list_dfw_policies`**: an int where NSX reported one, `null` where it did not — `null` means \"not retrieved\", never \"no rules\". The unfiltered listing asks for the count via `include_rule_count` (NSX omits the field otherwise); a name-filtered listing is resolved through the Policy Search API, which carries no rule counts, so every count there reads `null`. Any `null` adds a `rule_count_"},{"path":"references/cli-reference.md","content":"# VMware NSX Security CLI Reference\n\n## Global Options\n\n| Option | Short | Description |\n|--------|-------|-------------|\n| `--target` | `-t` | NSX Manager target name from config (uses `default_target` if omitted) |\n| `--config` | `-c` | Path to config file (overrides `VMWARE_NSX_SECURITY_CONFIG` env var) |\n| `--dry-run` | | Preview API call without executing (write commands only) |\n| `--help` | | Show help for any command |\n\n---\n\n## `policy` — DFW Policy Management\n\n### `policy list`\nList all DFW security policies.\n\n```bash\nvmware-nsx-security policy list [--target <name>]\n```\n\nOutput columns: ID, Display Name, Category, Seq#, Stateful, Rules\n\n### `policy get`\nGet full details of a DFW policy.\n\n```bash\nvmware-nsx-security policy get <policy-id> [--target <name>]\n```\n\n### `policy create`\nCreate a new DFW security policy.\n\n```bash\nvmware-nsx-security policy create <policy-id> \\\n  --name \"Display Name\" \\\n  [--category Ethernet|Emergency|Infrastructure|Environment|Application] \\\n  [--seq <number>] \\\n  [--description \"text\"] \\\n  [--dry-run] \\\n  [--target <name>]\n```\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `--name` | required | Human-readable policy name |\n| `--category` | Application | Policy evaluation category (validated; Ethernet evaluated first, Application last) |\n| `--seq` | 10 | Sequence number (lower = higher priority) |\n| `--description` | \"\" | Optional description |\n\n### `policy delete`\nDelete a DFW policy (requires no active rules).\n\n```bash\nvmware-nsx-security policy delete <policy-id> [--dry-run] [--target <name>]\n```\n\nPrompts for double confirmation. Fails if the policy contains rules.\n\n---\n\n## `rule` — DFW Rule Management\n\n### `rule list`\nList all rules in a policy.\n\n```bash\nvmware-nsx-security rule list <policy-id> [--target <name>]\n```\n\nOutput columns: ID, Display Name, Action, Direction, Disabled, Logged\n\n### `rule stats`\nGet packet/byte hit-count statistics for a rule.\n\n```bash\nvmware-nsx-security rule stats <policy-id> <rule-id> [--target <name>]\n```\n\nOutput fields: `packet_count`, `byte_count`, `session_count`, `hit_count`\n(summed across enforcement points), `popularity_index` (max).\n\n### `rule delete`\nDelete a DFW rule.\n\n```bash\nvmware-nsx-security rule delete <policy-id> <rule-id> [--dry-run] [--target <name>]\n```\n\nPrompts for double confirmation.\n\n---\n\n## `group` — Security Group Management\n\n### `group list`\nList all security groups.\n\n```bash\nvmware-nsx-security group list [--target <name>]\n```\n\n### `group get`\nGet group details including membership criteria and effective VM members.\n\n```bash\nvmware-nsx-security group get <group-id> [--target <name>]\n```\n\n### `group delete`\nDelete a security group (checks for DFW references first).\n\n```bash\nvmware-nsx-security group delete <group-id> [--dry-run] [--target <name>]\n```\n\nRefuses deletion if the group is a member of another group, or is\nreferenced by any DFW or gateway-firewall rule (source, destination, or\napplied-to scope) or by a policy-level s"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2197,"uniquenessScore":40,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T04:26:16.410Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T04:26:16.410Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-09T19:19:00.837Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}