Back to skill

Security audit

xcpng-aiops

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate Xen Orchestra operations skill, but it needs Review because it combines high-impact infrastructure write actions with mutable package execution and weak built-in authorization controls.

Install only if you trust the xcpng-aiops package publisher and can constrain it. Use a dedicated least-privilege Xen Orchestra account, prefer read-only tokens for triage, avoid storing the master password in synced or version-controlled MCP config, protect ~/.xcpng-aiops and MCP config permissions, and pin/verify the executable package version before using write tools on production infrastructure.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (2)

T08 · Insecure Dependencies

Error
Location
SKILL.md:57
Finding
Unpinned Third-Party Packages Are Downloaded and Executed<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:57-71`; related MCP configuration at `references/setup-guide.md:76-81` **Vulnerability Type**: Unpinned dependency retrieval and execution **Risk Level**: High ### Vulnerable Code ```markdown ```bash uv tool install xcpng-aiops xcpng-aiops init # interactive wizard: XO URL + encrypted token xcpng-aiops doctor # XO reachability + token validity + pool count ``` Or as an OpenClaw plugin, which installs this skill and its MCP server together: ```bash openclaw plugins install clawhub:@zw008/xcpng-aiops openclaw skills info xcpng-aiops # expect: Visible to model: yes ``` Needs `uvx` on `PATH`: the MCP server is fetched with uv, pinned to this release. ``` The related MCP configuration also invokes the package without an explicit version: ```json { "mcpServers": { "xcpng-aiops": { "command": "uvx", "args": ["--from", "xcpng-aiops", "xcpng-aiops-mcp"], "env": { "XCPNG_AIOPS_MASTER_PASSWORD": "your-master-password" } } } } ``` ### Technical Analysis The documented installation and MCP launch commands retrieve executable third-party packages from external package or plugin registries without specifying an immutable version, artifact digest, or verified signature. Although `SKILL.md` states that the MCP server is “pinned to this release,” the documented `uvx --from xcpng-aiops` invocation contains no visible version constraint. Consequently, the effective code executed by a future installation can differ from the code that was reviewed during this audit. This creates a software supply-chain trust boundary. A compromised publisher account, registry, package namespace, plugin namespace, or future malicious package release could replace the expected implementation with attacker-controlled code. Because package installation and MCP startup execute code locally, compromise would not be limited to Xen Orchestra API behavior. The reviewed project contains ...[truncated 1717 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every package and plugin command to an exact reviewed version: ```bash uv tool install "xcpng-aiops==<reviewed-version>" uvx --from "xcpng-aiops==<reviewed-version>" xcpng-aiops-mcp ``` 2. Use an exact immutable ClawHub release identifier rather than a mutable package name or latest tag. 3. Publish and verify cryptographic hashes or signed provenance for all distributed artifacts. 4. Use a lockfile with fully resolved transitive dependency versions and integrity hashes. 5. Ensure documentation and metadata use the same package version as the reviewed Skill release. 6. Run the MCP server in a restricted environment with: - A dedicated unprivileged operating-system account. - Minimal filesystem access. - A restricted environment-variable set. - Network access limited to the intended Xen Orchestra endpoint and required package infrastructure. 7. Add automated checks that reject unpinned dependency and plugin commands in release documentation. 8. Provide the executable package source or a reproducible-build reference so the implementation can be audited alongside the Skill instructions. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/cli-reference.md:77
Finding
Documented Secret Injection Methods Expose Credentials in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `references/cli-reference.md:77-84`; related MCP configuration at `references/setup-guide.md:76-87` **Vulnerability Type**: Plaintext secret exposure through command-line arguments and configuration files **Risk Level**: Medium ### Vulnerable Code ```markdown ## Secrets (encrypted store) ```bash xcpng-aiops secret set <target> [--value <token>] # omit --value to be prompted (hidden) xcpng-aiops secret list # names only xcpng-aiops secret rm <target> xcpng-aiops secret migrate # import legacy plaintext .env xcpng-aiops secret rotate-password # re-encrypt under a new master password ``` ``` The MCP setup guide additionally recommends embedding the master password directly in configuration: ```json { "mcpServers": { "xcpng-aiops": { "command": "uvx", "args": ["--from", "xcpng-aiops", "xcpng-aiops-mcp"], "env": { "XCPNG_AIOPS_MASTER_PASSWORD": "your-master-password" } } } } ``` ```markdown MCP clients do **not** inherit your shell environment — the master password (and any `XCPNG_*` overrides) must be in the `env` block. ``` ### Technical Analysis The `--value <token>` option places the Xen Orchestra token directly in the command line. Command-line secrets can be retained in shell history, terminal transcripts, process-monitoring systems, audit records, crash diagnostics, and process argument listings. The token is therefore exposed before it reaches the encrypted secret store. The MCP example places `XCPNG_AIOPS_MASTER_PASSWORD` directly in a static JSON configuration. Unless protected by a separate secret-management mechanism and strict file permissions, this stores the secret-store master password in plaintext. Anyone able to read that configuration can potentially unlock `~/.xcpng-aiops/secrets.enc`. This weakens the documented encryption design: protecting the encrypted token store provides limited ...[truncated 2106 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove or deprecate the `--value <token>` argument. 2. Accept tokens only through safer channels, such as: - Hidden interactive input. - Standard input with explicit controls against terminal echo. - A dedicated inherited file descriptor. - An operating-system credential store or approved secret provider. 3. If command-line token input must remain for compatibility, display a prominent warning that it can expose the token through history and process metadata. 4. Do not recommend placing a literal master password in MCP JSON configuration. 5. Integrate with platform-native secret references, an OS keychain, or an MCP runtime secret provider. 6. Where runtime environment injection is unavoidable: - Inject the value only when the process starts. - Restrict the environment to the MCP process. - Prevent environment logging. - Avoid storing the value in shell initialization files. 7. Apply strict permissions to MCP configuration and secret material: ```bash chmod 600 <mcp-config> chmod 600 ~/.xcpng-aiops/secrets.enc chmod 700 ~/.xcpng-aiops ``` 8. Remove the legacy plaintext `XCPNG_<TARGET>_TOKEN` fallback after a documented migration period. 9. Add secret-scanning guidance for shell history, configuration repositories, backups, CI logs, and support bundles. 10. Recommend immediate XO token revocation and rotation if a token or master password is exposed. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (15)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
```bash
xcpng-aiops init                    # onboarding wizard: XO URL, TLS verify (default yes), encrypted token
xcpng-aiops doctor [--skip-auth]    # config + secret store + XO reachability + pool count
xcpng-aiops overview [-t xo1]       # one-shot fleet health summary (JSON)
xcpng-aiops mcp                     # start the MCP server (stdio)
```
Confidence
70% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Credential Access

High
Category
Privilege Escalation
Content
xcpng-aiops secret set <target> [--value <token>]   # omit --value to be prompted (hidden)
xcpng-aiops secret list                             # names only
xcpng-aiops secret rm <target>
xcpng-aiops secret migrate                          # import legacy plaintext .env
xcpng-aiops secret rotate-password                  # re-encrypt under a new master password
```
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Session Persistence

Medium
Category
Rogue Agent
Content
metadata: {"openclaw":{"requires":{"anyBins":["xcpng-aiops","uvx"]},"optional":{"env":["XCPNG_AIOPS_CONFIG","XCPNG_AIOPS_MASTER_PASSWORD"]},"homepage":"https://github.com/AIops-tools/XCPng-AIops","emoji":"🖥️","os":["macos","linux"]}}
compatibility: >
  Standalone, self-governed XCP-ng operations via Xen Orchestra's REST API /rest/v0. REQUIRES a Xen Orchestra instance (XO from sources or the Xen Orchestra Appliance, 5.x) — XO is the management plane; direct per-host XAPI access is out of scope for v0.1. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency.
  All write operations are audited to a local SQLite DB under ~/.xcpng-aiops/ (relocatable via XCPNG_AIOPS_HOME).
  Credentials: Each XO target's personal authentication token is stored ENCRYPTED in ~/.xcpng-aiops/secrets.enc (Fernet/AES-128 + scrypt-derived key) — never plaintext on disk. Run 'xcpng-aiops init' to onboard, or 'xcpng-aiops secret set <target>' to add one (create the token in the XO UI: user menu → Personal tokens, or `xo-cli --createToken`). The store is unlocked by a master password from XCPNG_AIOPS_MASTER_PASSWORD (non-interactive/MCP/CI) or an interactive prompt (CLI on a TTY). A legacy plaintext env var XCPNG_<TARGET_NAME_UPPER>_TOKEN is still honoured as a fallback with a deprecation warning (migrate with 'xcpng-aiops secret migrate'). The token is sent in headers (Authorization: Bearer + authenticationToken cookie) at request time and held only in memory; tokens are never logged or echoed.
  Destructive operations (snapshot delete/revert, vm stop/reboot/migrate) require double confirmation at the CLI layer and support --dry-run; every write MCP tool takes a dry_run preview. A dry_run MAY read (that is how it can tell you the call would be refused) but never writes, records no undo, and is audited like any other governed call. All write tools pass through the @governed_tool decorator (budget guard + audi
...[truncated 25 chars]
Confidence
84% confidence
Finding
The skill persists sensitive operational state locally, including audit logs and encrypted XO authentication tokens, and also honors a legacy plaintext token environment variable fallback. Persistent credential/session material increases exposure to local compromise, accidental leakage through environment inspection, backups, or filesystem theft, particularly on shared workstations or CI runners.

Session Persistence

Medium
Category
Rogue Agent
Content
| Tasks | `task_list` | Read |
| Undo | `undo_list`, `undo_apply` | Read + replay |

**Harness features that light up**: `vm_start`↔`vm_stop` record each other as inverses (with `_undo_id`); `vm_migrate` captures the REAL source host BEFORE moving and records "migrate back"; `snapshot_create` captures the REAL snapshot id from the XO response and records "delete THAT snapshot". `snapshot_delete` and `snapshot_revert` are `risk_level=high`, capture BEFORE state, and declare no undo (irreversible). Every write takes `dry_run=True` (may read, never writes; no undo; audited). All 29 tools are audit-logged under `~/.xcpng-aiops/` and pass through the budget/runaway guard, each carrying a descriptive risk tier into its audit row. Start any triage with `overview`.

## CLI Quick Reference
Confidence
77% confidence
Finding
The tool records all writes and undo metadata under a local state directory, which means operational history and reversal descriptors persist across sessions. In this context, persistent audit/undo state can expose infrastructure details or enable unauthorized replay of prior actions if local access controls are weak, making the issue more significant because the skill manages production virtualization resources.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The skill advertises a bounded set of 29 MCP tools for XCP-ng/XO operations, but the same documentation also exposes additional operational capabilities such as initialization and secret-management commands. That mismatch can mislead users, reviewers, or policy engines about the real attack surface, especially because secret onboarding and token rotation materially affect credentials and trust boundaries.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill repeatedly describes a governance/policy harness, but later states there is no approval gate, no read-only switch, and no policy file enforcing writes. In an ops skill that can stop, reboot, migrate, revert, and delete resources, this discrepancy is dangerous because users may wrongly assume preventative controls exist when the mechanism is only audit and labeling.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
There is no read-only switch, policy file, or approval gate.

- **Audit is the guarantee, and it is not bypassable.** Every operation — MCP and CLI alike — is logged to `~/.xcpng-aiops/audit.db` (relocatable via `XCPNG_AIOPS_HOME`): params (secrets redacted), result, status, duration, and the risk tier. The CLI writes the same row the MCP path does.
- The XO token is stored **encrypted** in `~/.xcpng-aiops/secrets.enc` (Fernet/AES-128 + scrypt key derivation; chmod 600) — never plaintext on disk; the master password is never stored, only a per-store salt + ciphertext.
- `XCPNG_AUDIT_APPROVED_BY` / `XCPNG_AUDIT_RATIONALE` are optional annotations recorded on the audit row (who/why); they are never required and never block.
- **Budget / runaway guard** — a safety backstop, not authorization: caps cumulative tool calls and wall-time, and trips on tight task-poll loops.
- Writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI; CLI writes execute through the same governed tools, so they are audited + undo-recorded.
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
## Authorization is not this tool's job — decide it where it belongs

Whether a write should happen is your decision, or the account's. The tool does
not gate it — there is no read-only switch and no approval prompt to configure.
The two right places to control read vs write:

- **The Xen Orchestra account whose token you connect with.** Give that XO user
Confidence
95% confidence
Finding
The guardrail explicitly states the tool does not enforce read-only mode or approval for write actions, relying instead on external account permissions or prompting. In an agentic context, prompt-level restrictions are not a strong security boundary, so a misconfigured token or prompt injection could let the agent perform VM stop, reboot, migrate, snapshot revert/delete, or SR rescan operations without human approval.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The documentation explicitly says the tool harness records activity but does not gate writes, and that write execution is the agent's decision or depends on the connected Xen Orchestra account. In a skill that can start, stop, reboot, migrate VMs, revert snapshots, and rescan storage, this means the advertised governance layer may provide audit only, not enforcement, creating a real risk of unauthorized or unsafe state-changing actions.

Intent-Code Divergence

Medium
Confidence
90% confidence
Finding
The file creates a contradictory safety model: it says there is no approval gate, then later says high-risk tools require dry-run preview and double confirmation at the CLI. This inconsistency is dangerous because non-CLI callers, agents, or integrators may assume protections exist when they do not, leading to destructive operations like snapshot delete or revert being executed without the expected confirmation controls.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Stating that 'the tool records; it does not gate' and that writes are the agent's decision effectively delegates authorization to the calling agent or remote account, which can bypass organizational change-control expectations. In this context, the skill exposes operationally sensitive virtualization controls, so weak approval semantics can translate directly into VM outages, failed migrations, storage disruption, or destructive snapshot actions.

Session Persistence

Medium
Category
Rogue Agent
Content
|------|------|-------------|
| `task_list(status?, limit?)` | low | XO tasks (pending / success / failure). |

## Write semantics

- `dry_run=true` → preview dict (`{"dryRun": true, "would...": {...}}`). A dry-run **may
  read** — resolving ids and evaluating guards is what lets it tell you the call would be
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
```bash
xcpng-aiops init                    # onboarding wizard: XO URL, TLS verify (default yes), encrypted token
xcpng-aiops doctor [--skip-auth]    # config + secret store + XO reachability + pool count
xcpng-aiops overview [-t xo1]       # one-shot fleet health summary (JSON)
xcpng-aiops mcp                     # start the MCP server (stdio)
```
Confidence
80% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Session Persistence

Medium
Category
Rogue Agent
Content
(XO UI → Settings → Servers). **Per-host XAPI access is out of scope.**
- Python ≥ 3.11 (`uv tool install xcpng-aiops` handles the rest).

## 1. Create an XO authentication token

In the XO UI: user menu (top-right) → **Personal tokens** → create. Or from a
shell: `xo-cli --createToken`. Use a dedicated XO user with the least
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The guide shows an MCP client configuration with the master password embedded directly in the `env` block as plaintext. Even if intended as an example, this encourages users to place a highly sensitive secret in config files that may be readable by other local users, synced to dotfile repos, exposed in support bundles, or surfaced by client tooling; the surrounding text does not explicitly warn about those exposure paths.

Static analysis

Detected: suspicious.prompt_injection_instructions

Prompt-injection style instruction pattern detected.

Warn
Code
suspicious.prompt_injection_instructions
Location
references/agent-guardrails.md:42