Back to skill

Security audit

vmware-vks

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed VMware Kubernetes admin tool, but it gives agents access to live cluster credentials and production-changing actions that need careful review before use.

Install only for trusted operators on secured workstations, use least-privilege vCenter/Supervisor service accounts, avoid printing kubeconfigs into chat, prefer secure file paths or secret-manager injection, and review policy/audit settings before allowing agents to perform writes or retrieve credentials.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (23)

Credential Access

High
Category
Privilege Escalation
Content
| **VM Service** | `list_vm_snapshots` | Read |
| | `list_vm_groups` | Read |
| | `list_vm_network_interfaces` | Read |
| **Access** | `get_supervisor_kubeconfig` | Read |
| | `get_tkc_kubeconfig` | Write |
| | `get_harbor_info` | Read |
| | `list_namespace_storage_usage` | Read |
Confidence
82% confidence
Finding
The tool list exposes `get_supervisor_kubeconfig`, which by design returns authentication material capable of granting Kubernetes API access. In an agentic environment, a credential-returning read tool can enable unintended secret disclosure or lateral movement if outputs are echoed into chat history, logs, or downstream tools.

Credential Access

High
Category
Privilege Escalation
Content
| | `list_vm_groups` | Read |
| | `list_vm_network_interfaces` | Read |
| **Access** | `get_supervisor_kubeconfig` | Read |
| | `get_tkc_kubeconfig` | Write |
| | `get_harbor_info` | Read |
| | `list_namespace_storage_usage` | Read |
Confidence
84% confidence
Finding
`get_tkc_kubeconfig` is even more concerning because it is classified as a write capability and returns live cluster access credentials. In an LLM-agent context, this can directly expose privileged access tokens to the model context, logs, or untrusted plugins, enabling unauthorized access to tenant clusters.

Credential Access

High
Category
Privilege Escalation
Content
`delete_tkc_cluster` — requires `confirmed=True` and checks for running workloads. Rejects if found unless `force=True`.

**Credential handling**: `get_supervisor_kubeconfig` and `get_tkc_kubeconfig` return short-lived session tokens (not long-lived credentials). Tokens are derived from the authenticated vCenter session and expire when the session ends. Kubeconfig output is intended for local `kubectl` use — agents should write it to a file (`-o <path>`) rather than displaying tokens in conversation context.

> Full capability details and safety features: see `references/capabilities.md`
Confidence
89% confidence
Finding
The guidance to write kubeconfig to a file instead of displaying it reduces one exposure path but still acknowledges that the tool returns bearer-token-bearing kubeconfig. Because a saved kubeconfig is reusable during token lifetime and may persist on disk, this remains a real credential handling risk.

Credential Access

High
Category
Privilege Escalation
Content
`delete_tkc_cluster` — requires `confirmed=True` and checks for running workloads. Rejects if found unless `force=True`.

**Credential handling**: `get_supervisor_kubeconfig` and `get_tkc_kubeconfig` return short-lived session tokens (not long-lived credentials). Tokens are derived from the authenticated vCenter session and expire when the session ends. Kubeconfig output is intended for local `kubectl` use — agents should write it to a file (`-o <path>`) rather than displaying tokens in conversation context.

> Full capability details and safety features: see `references/capabilities.md`
Confidence
89% confidence
Finding
The guidance to write kubeconfig to a file instead of displaying it reduces one exposure path but still acknowledges that the tool returns bearer-token-bearing kubeconfig. Because a saved kubeconfig is reusable during token lifetime and may persist on disk, this remains a real credential handling risk.

Credential Access

High
Category
Privilege Escalation
Content
`delete_tkc_cluster` — requires `confirmed=True` and checks for running workloads. Rejects if found unless `force=True`.

**Credential handling**: `get_supervisor_kubeconfig` and `get_tkc_kubeconfig` return short-lived session tokens (not long-lived credentials). Tokens are derived from the authenticated vCenter session and expire when the session ends. Kubeconfig output is intended for local `kubectl` use — agents should write it to a file (`-o <path>`) rather than displaying tokens in conversation context.

> Full capability details and safety features: see `references/capabilities.md`
Confidence
89% confidence
Finding
The guidance to write kubeconfig to a file instead of displaying it reduces one exposure path but still acknowledges that the tool returns bearer-token-bearing kubeconfig. Because a saved kubeconfig is reusable during token lifetime and may persist on disk, this remains a real credential handling risk.

Credential Access

High
Category
Privilege Escalation
Content
vmware-vks tkc upgrade <name> -n <ns> --version <v> [--target <name>]
vmware-vks tkc delete <name> -n <ns> [--skip-workload-check] [--target <name>]

# Kubeconfig
vmware-vks kubeconfig supervisor -n <namespace> [--target <name>]
vmware-vks kubeconfig get <cluster-name> -n <namespace> [-o <path>] [--target <name>]
Confidence
81% confidence
Finding
The CLI reference publicly documents commands that retrieve Supervisor kubeconfig, confirming that the skill intentionally exposes live access credentials as part of normal operation. In a human-admin context this may be acceptable, but in an agent skill it materially increases the risk of credential exfiltration through prompts, transcripts, or tool chaining.

Credential Access

High
Category
Privilege Escalation
Content
vmware-vks tkc delete <name> -n <ns> [--skip-workload-check] [--target <name>]

# Kubeconfig
vmware-vks kubeconfig supervisor -n <namespace> [--target <name>]
vmware-vks kubeconfig get <cluster-name> -n <namespace> [-o <path>] [--target <name>]

# Harbor & Storage
Confidence
81% confidence
Finding
The `vmware-vks kubeconfig get` command retrieves TKC kubeconfig to a path, enabling export of active cluster credentials. This is a legitimate admin function but a true exposure risk for an AI agent because it can be invoked or suggested in contexts where secret handling controls are weaker than in manual administration.

Credential Access

High
Category
Privilege Escalation
Content
- View recent operations: `vmware-audit log --last 20`
- View denied operations: `vmware-audit log --status denied`

**In-memory kubeconfig (v1.5.18+)**: kubeconfig for the Supervisor and TKC clusters — which embeds the vCenter session bearer token — is built as a Python dict and loaded into the kubernetes client via `load_kube_config_from_dict()`. The token never touches disk during normal MCP/CLI flow, eliminating the previous temp-file TOCTOU window. The explicit `kubeconfig get -o <path>` CLI export still writes to the user-chosen path for `kubectl` use.

vmware-policy is automatically installed as a dependency — no manual setup needed.
Confidence
87% confidence
Finding
This is another duplicate match on the same line, but the underlying issue is still valid: the skill processes bearer-token-embedded kubeconfig. The context makes it more dangerous because the skill is designed for AI agents, which commonly preserve and retransmit tool outputs.

Credential Access

High
Category
Privilege Escalation
Content
- View recent operations: `vmware-audit log --last 20`
- View denied operations: `vmware-audit log --status denied`

**In-memory kubeconfig (v1.5.18+)**: kubeconfig for the Supervisor and TKC clusters — which embeds the vCenter session bearer token — is built as a Python dict and loaded into the kubernetes client via `load_kube_config_from_dict()`. The token never touches disk during normal MCP/CLI flow, eliminating the previous temp-file TOCTOU window. The explicit `kubeconfig get -o <path>` CLI export still writes to the user-chosen path for `kubectl` use.

vmware-policy is automatically installed as a dependency — no manual setup needed.
Confidence
87% confidence
Finding
This is another duplicate match on the same line, but the underlying issue is still valid: the skill processes bearer-token-embedded kubeconfig. The context makes it more dangerous because the skill is designed for AI agents, which commonly preserve and retransmit tool outputs.

Credential Access

High
Category
Privilege Escalation
Content
- View recent operations: `vmware-audit log --last 20`
- View denied operations: `vmware-audit log --status denied`

**In-memory kubeconfig (v1.5.18+)**: kubeconfig for the Supervisor and TKC clusters — which embeds the vCenter session bearer token — is built as a Python dict and loaded into the kubernetes client via `load_kube_config_from_dict()`. The token never touches disk during normal MCP/CLI flow, eliminating the previous temp-file TOCTOU window. The explicit `kubeconfig get -o <path>` CLI export still writes to the user-chosen path for `kubectl` use.

vmware-policy is automatically installed as a dependency — no manual setup needed.
Confidence
87% confidence
Finding
This is another duplicate match on the same line, but the underlying issue is still valid: the skill processes bearer-token-embedded kubeconfig. The context makes it more dangerous because the skill is designed for AI agents, which commonly preserve and retransmit tool outputs.

Credential Access

High
Category
Privilege Escalation
Content
| Level | Meaning | Agent autonomy | Examples in this skill |
|:-:|---|---|---|
| **L1** | Read-only, raw data | Always auto-run | `check_vks_compatibility`, `get_supervisor_status`, `list_supervisor_storage_policies`, `list_namespaces`, `get_namespace`, TKC list/get, `get_supervisor_kubeconfig` |
| **L2** | Read + analysis / recommendation | Always auto-run | namespace quota analysis, TKC health correlation, storage policy compatibility checks |
| **L3** | Single write — user must approve | Only after explicit confirmation; destructive ops require double-confirm + `--dry-run` | `create_namespace`, `update_namespace`, `delete_namespace`, `create_tkc_cluster`, `upgrade_tkc_cluster`, `scale_tkc_cluster`, `delete_tkc_cluster` |
| **L4** | Multi-step plan / apply workflow | Plan generation auto; apply gated by user approval | *(roadmap — TKC fleet upgrades, multi-namespace bootstrapping plans)* |
Confidence
97% confidence
Finding
Classifying `get_supervisor_kubeconfig` as L1 and 'always auto-run' exposes cluster access material without requiring user confirmation. A kubeconfig can contain or enable retrieval of bearer tokens and API endpoints, so autonomous retrieval materially increases the chance of credential disclosure or unauthorized downstream cluster access.

Credential Access

High
Category
Privilege Escalation
Content
**Notes**:
- L1/L2 tools are always safe for agents to call without confirmation.
- L3 tools always pass through the `@vmware_tool` decorator: connection check → policy check → audit log → double-confirm.
- Kubeconfig retrieval returns short-lived session tokens; agents should write to file (`-o <path>`) rather than displaying tokens in conversation context. `get_tkc_kubeconfig` is **not** L1 for that reason — `output_path` truncates a caller-chosen file, so it is annotated `readOnlyHint: false` and a client should confirm it.

## 1. Supervisor Layer (Read-Only)
Confidence
95% confidence
Finding
This section documents retrieval of short-lived session tokens through kubeconfig generation, which is credential access by design. The risk is elevated because the protection described relies partly on callers behaving correctly rather than hard enforcement, so a misconfigured or overly permissive client could leak credentials to logs or chat history.

Credential Access

High
Category
Privilege Escalation
Content
**Notes**:
- L1/L2 tools are always safe for agents to call without confirmation.
- L3 tools always pass through the `@vmware_tool` decorator: connection check → policy check → audit log → double-confirm.
- Kubeconfig retrieval returns short-lived session tokens; agents should write to file (`-o <path>`) rather than displaying tokens in conversation context. `get_tkc_kubeconfig` is **not** L1 for that reason — `output_path` truncates a caller-chosen file, so it is annotated `readOnlyHint: false` and a client should confirm it.

## 1. Supervisor Layer (Read-Only)
Confidence
95% confidence
Finding
This section documents retrieval of short-lived session tokens through kubeconfig generation, which is credential access by design. The risk is elevated because the protection described relies partly on callers behaving correctly rather than hard enforcement, so a misconfigured or overly permissive client could leak credentials to logs or chat history.

Credential Access

High
Category
Privilege Escalation
Content
| Tool | What it returns |
|------|----------------|
| `get_supervisor_kubeconfig` | Kubeconfig for Supervisor-level K8s API |
| `get_tkc_kubeconfig` | Kubeconfig for a specific TKC cluster (stdout or write to file) |
| `get_harbor_info` | Per registry: `id`, `cluster`, `version`, `url`, `status` (health), `storage_used_mb` — status/storage come from a per-registry detail call and are null if it fails. Never returns credentials |
| `list_namespace_storage_usage` | PVC list and usage stats per Namespace |
Confidence
98% confidence
Finding
The tool list shows the skill can return kubeconfig content or write it to disk, both of which create credential exposure paths. Even when intended for legitimate cluster administration, returning access material through agent workflows raises the risk of accidental disclosure, overbroad access, or persistence in logs and transcripts.

Credential Access

High
Category
Privilege Escalation
Content
| Tool | What it returns |
|------|----------------|
| `get_supervisor_kubeconfig` | Kubeconfig for Supervisor-level K8s API |
| `get_tkc_kubeconfig` | Kubeconfig for a specific TKC cluster (stdout or write to file) |
| `get_harbor_info` | Per registry: `id`, `cluster`, `version`, `url`, `status` (health), `storage_used_mb` — status/storage come from a per-registry detail call and are null if it fails. Never returns credentials |
| `list_namespace_storage_usage` | PVC list and usage stats per Namespace |
Confidence
98% confidence
Finding
The tool list shows the skill can return kubeconfig content or write it to disk, both of which create credential exposure paths. Even when intended for legitimate cluster administration, returning access material through agent workflows raises the risk of accidental disclosure, overbroad access, or persistence in logs and transcripts.

Credential Access

High
Category
Privilege Escalation
Content
| Tool | What it returns |
|------|----------------|
| `get_supervisor_kubeconfig` | Kubeconfig for Supervisor-level K8s API |
| `get_tkc_kubeconfig` | Kubeconfig for a specific TKC cluster (stdout or write to file) |
| `get_harbor_info` | Per registry: `id`, `cluster`, `version`, `url`, `status` (health), `storage_used_mb` — status/storage come from a per-registry detail call and are null if it fails. Never returns credentials |
| `list_namespace_storage_usage` | PVC list and usage stats per Namespace |
Confidence
97% confidence
Finding
The specific mention of writing kubeconfig to file highlights credential export capability, which can be abused for persistence or exfiltration. In the context of an agent skill, a caller-controlled path also increases the chance of unsafe file operations or accidental placement in shared directories.

Credential Access

High
Category
Privilege Escalation
Content
| Tool | What it returns |
|------|----------------|
| `get_supervisor_kubeconfig` | Kubeconfig for Supervisor-level K8s API |
| `get_tkc_kubeconfig` | Kubeconfig for a specific TKC cluster (stdout or write to file) |
| `get_harbor_info` | Per registry: `id`, `cluster`, `version`, `url`, `status` (health), `storage_used_mb` — status/storage come from a per-registry detail call and are null if it fails. Never returns credentials |
| `list_namespace_storage_usage` | PVC list and usage stats per Namespace |
Confidence
97% confidence
Finding
The specific mention of writing kubeconfig to file highlights credential export capability, which can be abused for persistence or exfiltration. In the context of an agent skill, a caller-controlled path also increases the chance of unsafe file operations or accidental placement in shared directories.

Credential Access

High
Category
Privilege Escalation
Content
| Audit Trail | All write operations logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy) plus a local JSON-Lines mirror at `~/.vmware-vks/audit.log`, with timestamp, target, operation, parameters, result, user |
| Read-Only Majority | 15/23 tools are read-only |
| SSL Support | `verify_ssl: false` supported for self-signed vCenter certs (enterprise standard) |
| In-Memory Kubeconfig | Supervisor/TKC kubeconfig is constructed as a Python dict and loaded into the kubernetes client via `load_kube_config_from_dict()`. The vCenter session bearer token never persists to disk during MCP/CLI calls — eliminates the temp-file TOCTOU window present pre-v1.5.18. Explicit `kubeconfig get -o <path>` export still writes to the user-chosen file for downstream `kubectl` use. |

## Version Compatibility
Confidence
86% confidence
Finding
This is partially a false positive because the passage describes a security improvement, but it still reveals a remaining sensitive capability: writing kubeconfig to user-selected files. In practice that is a valid credential-access concern because exported kubeconfig can outlive the session and be mishandled by users or automation.

Credential Access

High
Category
Privilege Escalation
Content
| Audit Trail | All write operations logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy) plus a local JSON-Lines mirror at `~/.vmware-vks/audit.log`, with timestamp, target, operation, parameters, result, user |
| Read-Only Majority | 15/23 tools are read-only |
| SSL Support | `verify_ssl: false` supported for self-signed vCenter certs (enterprise standard) |
| In-Memory Kubeconfig | Supervisor/TKC kubeconfig is constructed as a Python dict and loaded into the kubernetes client via `load_kube_config_from_dict()`. The vCenter session bearer token never persists to disk during MCP/CLI calls — eliminates the temp-file TOCTOU window present pre-v1.5.18. Explicit `kubeconfig get -o <path>` export still writes to the user-chosen file for downstream `kubectl` use. |

## Version Compatibility
Confidence
86% confidence
Finding
This is partially a false positive because the passage describes a security improvement, but it still reveals a remaining sensitive capability: writing kubeconfig to user-selected files. In practice that is a valid credential-access concern because exported kubeconfig can outlive the session and be mishandled by users or automation.

Credential Access

High
Category
Privilege Escalation
Content
| Audit Trail | All write operations logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy) plus a local JSON-Lines mirror at `~/.vmware-vks/audit.log`, with timestamp, target, operation, parameters, result, user |
| Read-Only Majority | 15/23 tools are read-only |
| SSL Support | `verify_ssl: false` supported for self-signed vCenter certs (enterprise standard) |
| In-Memory Kubeconfig | Supervisor/TKC kubeconfig is constructed as a Python dict and loaded into the kubernetes client via `load_kube_config_from_dict()`. The vCenter session bearer token never persists to disk during MCP/CLI calls — eliminates the temp-file TOCTOU window present pre-v1.5.18. Explicit `kubeconfig get -o <path>` export still writes to the user-chosen file for downstream `kubectl` use. |

## Version Compatibility
Confidence
86% confidence
Finding
This is partially a false positive because the passage describes a security improvement, but it still reveals a remaining sensitive capability: writing kubeconfig to user-selected files. In practice that is a valid credential-access concern because exported kubeconfig can outlive the session and be mishandled by users or automation.

Credential Access

High
Category
Privilege Escalation
Content
environment: production
EOF

echo "VMWARE_VKS_VCENTER01_PASSWORD=your_password" > ~/.vmware-vks/.env
chmod 600 ~/.vmware-vks/.env

# 3. Verify
Confidence
93% confidence
Finding
The guide instructs users to place a live vCenter password directly into `~/.vmware-vks/.env`. Even with `chmod 600` and later base64 obfuscation, this creates a persistent plaintext-equivalent secret on disk that can be recovered by any local compromise, backup leakage, shell history mistake, or endpoint malware. In the context of a VKS/vCenter administration skill, these credentials can enable high-impact infrastructure access.

Session Persistence

Medium
Category
Rogue Agent
Content
`delete_tkc_cluster` — requires `confirmed=True` and checks for running workloads. Rejects if found unless `force=True`.

**Credential handling**: `get_supervisor_kubeconfig` and `get_tkc_kubeconfig` return short-lived session tokens (not long-lived credentials). Tokens are derived from the authenticated vCenter session and expire when the session ends. Kubeconfig output is intended for local `kubectl` use — agents should write it to a file (`-o <path>`) rather than displaying tokens in conversation context.

> Full capability details and safety features: see `references/capabilities.md`
Confidence
80% confidence
Finding
Advising agents to write kubeconfig to a file instead of displaying it mitigates chat leakage but introduces session persistence risk on disk. Even short-lived kubeconfigs can be harvested from local files, backups, shell history, or insecure paths before expiration, especially on multi-user systems or poorly secured workstations.

Session Persistence

Medium
Category
Rogue Agent
Content
| "Confirm before deleting anything" | **`confirmed=True` is required.** `delete_namespace` additionally refuses while TKC clusters still exist inside it, and `delete_tkc_cluster` refuses while workloads are running unless `force=True`. |
| "Use explicit limits for queries that may return large amounts of data" | **The list envelope.** `list_namespaces`, `list_supervisor_storage_policies` and `list_vm_classes` return `{items, returned, limit, total, truncated, hint}`, so the model reads truncation instead of guessing at it. These three read their collection in one un-paged call, so `total` is the real count and `truncated` is always `false`. |
| "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. |
| "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. |

---
Confidence
82% confidence
Finding
The documentation states that every write is recorded to `~/.vmware/audit.db` before the model sees the result, which implies persistent local storage of operational actions. In a skill that can handle destructive changes and credential-adjacent workflows, persistent audit records can expose sensitive environment metadata, resource names, user actions, and possibly request parameters if the database is readable by unintended local users or collected insecurely.

Static analysis

No suspicious patterns detected.