Back to skill

Security audit

ucloud-infra

Security checks for vulnerabilities and agentic risk

Overview

This UCloud management skill is purpose-aligned, but it handles powerful cloud credentials and commands in unsafe ways that deserve review before use.

Install only after reviewing the code and using least-privilege, revocable UCloud credentials. Avoid running it with untrusted input, treat local operation logs and agent transcripts as potentially sensitive, and prefer a fixed version that uses argument-array execution, redacts secrets, narrows permissions, and adds explicit confirmation for destructive actions.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
ucloud.mjs:158
Finding

Shell Command Injection Through Unquoted CLI Arguments

Content
View full analysis

Vulnerability Details

File Location: ucloud.mjs, lines 158–167
Vulnerability Type: OS command injection
Risk Level: High

Vulnerable Code

js
const fullArgs = [...baseArgs, ...args];
const command = "ucloud " + fullArgs.join(" ");
try {
  const { stdout, stderr } = await execAsync(command);
  if (stderr) {
    return { success: false, error: stderr };
  }

User-controlled arguments reach this function through handlers such as the UHost creation handler:

js
const createArgs = ["uhost", "create", "--cpu", values.cpu, "--memory-gb", values["memory-gb"], "--password", values.password, "--image-id", values["image-id"]];
if (values.name) createArgs.push("--name", values.name);
if (values.count) createArgs.push("--count", values.count);
result = await runUcloudCommand(createArgs);

Technical Analysis

runUcloudCommand() constructs a single command string by joining argument values with spaces and executes it through child_process.exec(). The exec() API invokes a command shell, so shell metacharacters in any argument are interpreted as command syntax rather than preserved as literal argument data.

Many values incorporated into the command are externally controlled, including --name, --password, resource identifiers, image identifiers, numeric fields, region, zone, project ID, and credentials obtained from environment variables. The implementation performs no shell escaping, quoting, allowlist validation, or character restrictions before execution.

For example, a value containing a semicolon, command substitution, redirection, or shell pipeline can terminate or alter the intended UCloud command and introduce an additional command.

Attack Path

  1. An attacker supplies a crafted value through an accepted command-line option, such as a --name value containing shell metacharacters.
  2. parseArgs() accepts the value as a string.
  3. The relevant resource handler ...[truncated 1193 chars]
Remediation
View remediation

Remediation Suggestions

Replace shell-string execution with an API that invokes the executable directly and accepts an argument array, such as execFile() or spawn():

js
import { execFile } from "node:child_process";
import { promisify } from "node:util";

const execFileAsync = promisify(execFile);

async function runUcloudCommand(args, options = {}) {
  const fullArgs = [...baseArgs, ...args];
  const { stdout, stderr } = await execFileAsync(
    "ucloud",
    fullArgs,
    {
      shell: false,
      maxBuffer: 1024 * 1024
    }
  );
}

Additional hardening should include:

  • Explicitly set shell: false.
  • Validate numeric options using strict numeric parsing and acceptable ranges.
  • Restrict regions, zones, modes, traffic modes, and resource types to allowlisted values.
  • Validate resource identifiers against documented UCloud identifier formats.
  • Reject control characters and unexpected newline characters.
  • Resolve the expected UCloud executable through a trusted absolute path where feasible.
  • Run the skill under a minimally privileged operating-system account.
  • Add security tests containing semicolons, command substitutions, redirects, pipelines, spaces, and newlines to ensure they remain literal arguments.

T09 · Insecure Skill Coding Practices

Error
Location
ucloud.mjs:144
Finding

Cloud API Keys and Resource Passwords Exposed Through Process Arguments and Error Output

Content
View full analysis

Vulnerability Details

File Location: ucloud.mjs, lines 144–172
Vulnerability Type: Sensitive information exposure
Risk Level: High

Vulnerable Code

js
const baseArgs = [
  "--public-key", publicKey,
  "--private-key", privateKey,
  "--json"
];

// Some commands (like 'region') don't accept project-id, region, zone
if (!skipProjectParams) {
  baseArgs.push("--project-id", projectId);
  baseArgs.push("--region", region);
  // Some commands (like 'eip list') don't accept --zone
  if (!skipZone) {
    baseArgs.push("--zone", zone);
  }
}

const fullArgs = [...baseArgs, ...args];
const command = "ucloud " + fullArgs.join(" ");
try {
  const { stdout, stderr } = await execAsync(command);
  if (stderr) {
    return { success: false, error: stderr };
  }
  try {
    const data = JSON.parse(stdout);
    return { success: true, data: data };
  } catch {
    return { success: true, raw_output: stdout };
  }
} catch (error) {
  return { success: false, error: error.message };
}

UHost passwords are also passed in the generated command:

js
const createArgs = ["uhost", "create", "--cpu", values.cpu, "--memory-gb", values["memory-gb"], "--password", values.password, "--image-id", values["image-id"]];

Technical Analysis

The UCloud public key and private key are embedded directly in the command line for every CLI invocation. UHost creation passwords are similarly inserted into process arguments.

Command-line arguments may be visible to local process-inspection facilities, monitoring agents, debugging tools, audit systems, and other users depending on operating-system configuration. Because the code uses exec() with a complete command string, the parent shell also receives the secrets.

In addition, failures are returned using error.message. Errors generated by Node.js command execution commonly include the failed command string. Consequently, th ...[truncated 1751 chars]

Remediation
View remediation

Remediation Suggestions

  • Use the UCloud CLI's supported environment-based, protected configuration-file, credential-helper, or standard-input mechanism instead of including private credentials in command arguments.
  • Use execFile() or spawn() with an argument array to eliminate the shell command string, although this alone does not prevent process-list exposure of argument-based secrets.
  • Avoid passing resource passwords on the command line. Prefer standard input, a protected temporary file supported by the CLI, or a dedicated API client that sends secrets directly over an authenticated connection.
  • Never return raw child-process error messages to callers.
  • Create a centralized redaction function that removes the public key, private key, passwords, and other sensitive values from stdout, stderr, exceptions, and structured results.
  • Return generic external errors while retaining only sanitized diagnostic metadata.
  • Ensure application and agent logs do not retain secrets already exposed in prior runs.
  • Rotate any API credentials or passwords that may already have appeared in process telemetry or error logs.
  • Restrict UCloud credentials to the minimum required cloud permissions and use short-lived credentials where supported.
  • Apply restrictive permissions to any credential configuration files and operational logs.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
.claude/settings.local.json:2
Finding

Overly Broad Preapproval of Arbitrary Node.js Commands

Content
View full analysis

Vulnerability Details

File Location: .claude/settings.local.json, lines 2–5
Vulnerability Type: Excessive tool permission
Risk Level: Medium

Vulnerable Code

json
"permissions": {
  "allow": [
    "Bash(node:*)"
  ]
}

Technical Analysis

The permission rule preapproves every Bash command whose command pattern begins with or matches node, rather than limiting execution to the audited ucloud.mjs entry point.

Node.js can execute arbitrary inline JavaScript through options such as -e, load external modules, read and write local files, start child processes, and access environment variables. Therefore, granting unrestricted Node.js execution is effectively a broad local code-execution capability rather than a narrowly scoped permission needed to operate this skill.

This setting does not by itself prove malicious execution. However, it weakens the least-privilege boundary and can allow an untrusted prompt, compromised workflow, or command-injection chain to invoke unrelated Node.js code without a separate permission decision.

Attack Path

  1. The skill environment loads the local permission configuration.
  2. An attacker-controlled instruction or compromised workflow requests execution of an arbitrary Node.js command instead of the expected skill entry point.
  3. The command matches the broad Bash(node:*) allow rule.
  4. The command is executed without a narrowly scoped approval check.
  5. Arbitrary JavaScript can access files, environment variables, network interfaces, and child-process APIs available to the agent account.

Impact Assessment

Exploitation can provide code execution with the privileges of the agent process. This can expose environment variables containing UCloud credentials, permit modification of accessible files, invoke other executables, or interact with network services.

The practical scope depends on the surrounding agent permission model and the oper ...[truncated 195 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the broad Bash(node:*) permission.
  • Restrict execution to the exact audited script path and required argument pattern if the permission system supports that granularity.
  • Require explicit user approval for inline JavaScript, alternate script paths, Node.js debugging options, preload modules, and other general-purpose Node.js invocations.
  • Run the skill in a sandbox with a minimal environment, restricted filesystem access, and limited network access.
  • Do not expose UCloud secrets to unrelated Node.js processes.
  • Combine the narrower permission rule with strict input validation and the removal of shell-based command construction.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill description and operational guidance are presented in Chinese, and the file does not indicate that this is a region-specific skill or provide an opt-in/alternative language. Under the stated policy, forcing a specific language without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill declares required environment variables containing cloud API credentials but does not define any explicit tool scope or allowed-tools boundary. In a high-impact cloud management skill that can create, delete, and reconfigure infrastructure, missing scope constraints increases the risk that the runtime or calling agent can access secrets more broadly than intended or invoke capabilities without clear limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The title and description force a specific language/locale for user-facing instructions. Under the policy, language restrictions are only acceptable when the skill offers user choice or clearly documents a justified regional constraint, which this file does not do.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation states that create/delete operations log full action parameters, and the skill examples include sensitive fields such as --password and cloud resource identifiers. Logging raw parameters to JSONL in the working directory can expose secrets to other users, processes, backups, or later exfiltration, especially in an infrastructure-management context where the same logs may contain database or host credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill reads UCLOUD_PUBLIC_KEY and UCLOUD_PRIVATE_KEY from environment variables and passes them on the command line to ucloud via exec, which can expose secrets through process listings, shell history equivalents, crash telemetry, or other local monitoring. In the context of a cloud-management skill, compromise of these credentials can enable broad unauthorized access to cloud resources, making this substantially more dangerous than ordinary secret handling issues.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code builds and executes ucloud CLI commands via a subprocess, including destructive actions such as uhost delete, but provides no confirmation prompt or explicit user-facing warning before execution. While create/delete events are logged after the fact, logging is not the same as disclosure or confirmation of potentially impactful infrastructure changes.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.