Back to skill

Security audit

Proxmox Management

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims: it manages Proxmox resources using a user-provided API token, with disclosed destructive operations and approval markers.

Install only with a dedicated Proxmox API token scoped to the nodes, VMs, containers, and snapshot permissions you actually want the agent to manage. Treat stop, shutdown, rollback, and snapshot deletion as live-infrastructure operations that can interrupt services or remove recovery points. For stronger installation safety, pin and audit the Python dependencies before use.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (1)

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Third-Party Dependencies Permit Unreviewed Package Updates

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-2
Additional Locations: SKILL.md:7, _meta.json:10, README.md:15
Vulnerability Type: Supply-chain risk caused by unbounded dependency versions
Risk Level: Medium

Vulnerable Code

requirements.txt:1-2:

text
proxmoxer>=2.0.0
requests>=2.0.0

SKILL.md:7:

yaml
python: ["proxmoxer>=2.0.0", "requests>=2.0.0"]

_meta.json:10:

json
"python": ["proxmoxer>=2.0.0", "requests>=2.0.0"]

README.md:15:

shell
pip install proxmoxer requests

Technical Analysis

The dependency specifications define only minimum versions and provide no exact version pins, upper bounds, lockfile, or cryptographic hashes. The installation command in the README is even less restrictive and requests the latest available releases.

Consequently, installation results can change after the Skill has been reviewed. A future compromised, malicious, or incompatible release satisfying these constraints may be installed automatically. Python packages can execute code during installation and subsequently execute imported package code when the Skill starts.

This is particularly sensitive because proxmoxer runs in the same process as scripts/proxmox.py. At runtime, that process can access PVE_HOST, PVE_TOKEN_ID, and PVE_TOKEN_SECRET, as well as perform operations allowed by the associated Proxmox API token.

No evidence indicates that the currently named packages are malicious. The confirmed issue is the absence of reproducible, integrity-verified dependency resolution.

Attack Path

  1. An attacker compromises a dependency publisher account, distribution infrastructure, or a future dependency release.
  2. The attacker publishes a malicious version that satisfies proxmoxer>=2.0.0 or requests>=2.0.0.
  3. A user installs or updates the Skill dependencies using requirements.txt or th ...[truncated 1276 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to a specifically reviewed version using ==.
  2. Generate a lockfile containing the full transitive dependency graph rather than resolving dependencies afresh during each installation.
  3. Record package hashes and require integrity verification, for example with pip install --require-hashes -r requirements.txt.
  4. Review and update dependency pins through a controlled process that includes vulnerability scanning and regression testing.
  5. Keep dependency declarations synchronized across requirements.txt, SKILL.md, _meta.json, and README.md.
  6. Determine whether requests must be declared directly. Remove it as a direct dependency if the Skill does not directly require it, while still locking any transitive version selected for proxmoxer.
  7. Install dependencies from the official package index or a controlled internal mirror, and prohibit untrusted extra indexes.
  8. Continue enforcing least-privilege Proxmox API-token permissions so that compromise of the runtime dependency chain has limited infrastructure impact.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (12)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill declares environment-variable requirements containing sensitive Proxmox API credentials but does not define any explicit tool scope or allowed-tools restrictions. That increases the chance that an agent or surrounding runtime could expose or misuse those credentials through broader-than-necessary tool access, especially because the skill can perform privileged infrastructure actions such as power control and snapshot rollback.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest explicitly includes destructive actions such as shutdown, rollback, and delete without any warning about service interruption, data loss, or irreversibility. Because this skill manages live virtualization infrastructure, understated descriptions materially increase the risk of accidental invocation leading to outages, reverted state, or permanent loss of snapshots/resources.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Snapshot rollback is a destructive state-changing operation that can discard current VM/container state and cause service interruption or data loss. Relying only on an external approval mechanism means the script itself provides no safety barrier if it is called directly, misconfigured, or integrated into another execution path without the expected approval controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Snapshot deletion permanently removes recovery points and can hinder restoration after operator error or compromise. In this infrastructure-management context, the lack of in-file confirmation materially increases the risk of accidental or unauthorized destructive actions, especially if the script is invoked outside the intended approval framework.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest advertises broad infrastructure-management capabilities across nodes, VMs, and containers, but it does not describe any activation boundaries, approval requirements, or scope limitations. In an agent ecosystem, this can cause overbroad invocation and user misunderstanding, increasing the chance that the skill is used in contexts where destructive or privileged operations are not expected.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency specifier proxmoxer>=2.0.0 is unpinned, which allows materially different versions to be installed over time. That weakens build reproducibility and can unintentionally introduce vulnerable or incompatible releases into a privileged infrastructure-management skill.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
proxmoxer>=2.0.0
requests>=2.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
99% confidence
Finding

The dependency specifier requests>=2.0.0 is unpinned, so the installed version may vary by environment and time. Because requests has had multiple security advisories, leaving it unpinned increases the chance of resolving to an affected or otherwise unsafe version, especially in automation that may handle Proxmox credentials or API traffic.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
proxmoxer>=2.0.0
requests>=2.0.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
98% confidence
Finding

requests is referenced without a fixed version even though known advisories exist for some releases, so there is no way to verify whether deployed environments are affected. In the context of a Proxmox management skill, a vulnerable HTTP client could expose credentials, mishandle TLS/session state, or otherwise compromise administrative API interactions.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
87% confidence
Finding

The code uses user-controlled 'kind' in getattr(p.nodes(node), kind) without validating it in status_current(). That allows access to arbitrary proxmoxer sub-resources under a node rather than only 'qemu' or 'lxc', which can bypass the intended command scope and issue unexpected API calls if the object exposes compatible methods.

Content

Scanner excerpt · scripts/proxmox.py (reported line 54)May include surrounding context.

python
def status_current(p: ProxmoxAPI, node: str, kind: str, vmid: str):
    # kind is usually 'qemu' or 'lxc'
    endpoint = getattr(p.nodes(node), kind)
    return endpoint(vmid).status.current.get()

def action_vm(p: ProxmoxAPI, node: str, kind: str, vmid: str, action: str):

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
94% confidence
Finding

action_vm() performs dynamic attribute access on user-controlled 'kind' without validation before invoking an action. In a management skill with cluster control privileges, this can let an attacker steer requests to unintended Proxmox API resource paths and combine with the subsequent dynamic action call to perform operations outside the expected VM/container power-control scope.

Content

Scanner excerpt · scripts/proxmox.py (reported line 59)May include surrounding context.

python
def action_vm(p: ProxmoxAPI, node: str, kind: str, vmid: str, action: str):
    # action: start, stop, reboot, shutdown
    endpoint = getattr(p.nodes(node), kind)
    return getattr(endpoint(vmid).status, action).post()

def _vm_endpoint(p: ProxmoxAPI, node: str, kind: str, vmid: str):

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/proxmox.py (reported line 60)May include surrounding context.

python
def action_vm(p: ProxmoxAPI, node: str, kind: str, vmid: str, action: str):
    # action: start, stop, reboot, shutdown
    endpoint = getattr(p.nodes(node), kind)
    return getattr(endpoint(vmid).status, action).post()

def _vm_endpoint(p: ProxmoxAPI, node: str, kind: str, vmid: str):
    if kind not in ("qemu", "lxc"):

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/proxmox.py (reported line 65)May include surrounding context.

python
def _vm_endpoint(p: ProxmoxAPI, node: str, kind: str, vmid: str):
    if kind not in ("qemu", "lxc"):
        jprint({"ok": False, "error": f"kind must be 'qemu' or 'lxc', got '{kind}'"}, 2)
    return getattr(p.nodes(node), kind)(vmid)

def list_snapshots(p: ProxmoxAPI, node: str, kind: str, vmid: str):
    return _vm_endpoint(p, node, kind, vmid).snapshot.get()

Static analysis

No suspicious patterns detected.