Back to skill

Security audit

huawei-cloud-kunpeng-source-code-migrate

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly purpose-aligned, but it needs Review because it can provision paid cloud infrastructure, enable root password SSH, run arbitrary remote commands, install packages, and persist SSH secrets in temp files.

Install only if you are comfortable giving the agent SSH access to a target server and, if needed, authority to create paid Huawei Cloud resources. Prefer an existing disposable test server or a non-root account, review every install/provisioning command before execution, avoid storing SSH passwords in /tmp longer than necessary, and delete or rotate provisioned credentials and cloud resources after the assessment.

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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (35)

Tainted flow: 'env_file' from os.environ.get (line 709, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
f"export KUNPENG_SERVER_PORT=\"{port}\"\n"
        f"export KUNPENG_SERVER_USER=\"{user}\"\n"
    )
    with open(env_file, 'w', encoding='utf-8') as f:
        f.write(content)
    try:
        os.chmod(env_file, 0o600)
Confidence
90% confidence
Finding
The output path is derived from TEMP/TMP environment variables and then opened for writing without validation. In an agent context, a hostile or manipulated environment could redirect the file write to an unintended location, causing credential/config file overwrite or placement in an attacker-observable path.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill performs sensitive operations including shell execution, environment-variable credential handling, local file reads/writes, SSH access, and cloud provisioning, yet no declared permissions are present. This creates a transparency and policy-enforcement gap: a host agent may invoke a highly privileged skill without clear consent boundaries or capability gating.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The skill instructs the agent to run `chmod -R +r '<SOURCE_PATH>'` on the remote source tree when permission errors occur. A migration assessment skill should be read-only; recursively changing permissions on user code can alter system state, broaden access to sensitive files, and violate least-privilege expectations. In this context, the danger is higher because the skill operates over SSH on arbitrary remote paths supplied during analysis.

Intent-Code Divergence

Medium
Confidence
89% confidence
Finding
The document establishes a security requirement that all remote command execution must go through ssh_client.py, but later verification steps still rely on deprecated remote_exec usage. In a skill that performs SSH-based actions against remote servers and handles credentials, inconsistent execution guidance can lead implementers to use less-controlled code paths, weakening guarantees around credential handling, logging, and command execution behavior.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The comments explicitly state that no password is generated and that passwordless SSH is used, but the script actually generates a root password, enables PermitRootLogin yes and PasswordAuthentication yes, and stores the credential for later use. This mismatch is dangerous because operators and downstream agents may make trust decisions based on the comments, while the real behavior materially weakens server access controls and exposes a high-value root credential.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The documentation claims the password is never stored on disk, but the implementation explicitly reads it from `/tmp/kunpeng_server_env.sh` or `%TEMP%/kunpeng_server_env.sh`. This mismatch can cause operators to handle credentials less carefully than warranted, and on multi-user systems a temp-file secret is materially more exposed than an in-memory-only secret.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The help text encourages persisting `MIGRATE_SSH_PASS` in `/tmp/kunpeng_server_env.sh`, which is an unsafe pattern for storing SSH credentials in a predictable temp location. In this skill's context, the password grants remote server access, so disclosure can lead directly to compromise of the migration host and any source code on it.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill directs the agent to upload and execute an installation script on a remote host and perform package-management actions automatically, but it does not require an explicit confirmation or warning immediately before making those system changes. In this context, that creates a real safety issue because an agent could modify a user's server state, install software, and alter dependencies on the wrong host or without sufficiently informed consent.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill instructs the agent/user to run an installation script that may install packages and write into system locations such as /usr/local without an explicit warning, confirmation gate, or clear explanation of system impact. In an agent context, this is risky because it normalizes privileged modification of the host and could lead to unintended package changes, persistence, or breakage if executed automatically.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The local scanning workflow processes user source code and writes reports to a fixed path (/home/devkit-report) without any privacy, confidentiality, overwrite, or multi-user safety warning. In a security-sensitive environment, source code may contain proprietary or secret material, and saving analysis artifacts to a predictable shared location increases risk of disclosure or accidental exposure.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The troubleshooting steps tell users to open SSH in the host firewall with broad allow rules and do not include equivalent cautions about restricting source addresses or minimizing exposure. In a skill centered on remote access and cloud provisioning, this guidance can materially increase attack surface and lead to unintended SSH exposure.

Vague Triggers

Medium
Confidence
93% confidence
Finding
After explicitly requiring replacement of remote_exec with ssh_client.py, the document continues to provide deprecated remote_exec command examples in Task 2/3. This ambiguity is security-relevant because operators may copy unsafe or unsupported invocation patterns directly, bypassing the intended credential-protection and unified SSH controls in ssh_client.py.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
`cmd_exec` exposes arbitrary remote shell command execution over SSH with no guardrails, allowlist, or safety warning. In an agent skill, this is especially dangerous because upstream user/project data may be transformed into shell strings, enabling destructive or unintended execution on the remote server.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
# Interactive mode (with confirmation prompt)
bash <skill_dir>/scripts/provision_kunpeng_server.sh

# Automated mode (skip confirmation, for skill-driven execution)
bash <skill_dir>/scripts/provision_kunpeng_server.sh --confirm

# Specify SSH source CIDR (recommended for security)
Confidence
86% confidence
Finding
The documentation explicitly supports a non-interactive '--confirm' mode 'for skill-driven execution' for provisioning billable cloud infrastructure. In agent contexts, this can enable resource creation without a fresh, explicit user approval at execution time, creating financial and environmental impact and increasing the risk of unintended infrastructure exposure.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| Option | Description | Default |
|--------|-------------|---------|
| `--confirm` | Skip confirmation prompt | Off (interactive) |
| `--ssh-source=<CIDR>` | Restrict SSH inbound to this CIDR | Auto-detect agent IP /32 |

> **⚠️ Security: SSH source CIDR must NEVER be set to `0.0.0.0/0` (allow-all).** The script auto-detects the agent's public IP and restricts SSH to `<IP>/32`. If auto-detection fails, the script aborts and requires `--ssh-source` to be specified explicitly.
Confidence
83% confidence
Finding
Documenting an option whose purpose is to skip the confirmation prompt creates an easy path for an agent to bypass human review before provisioning. Even though the file later says the script must not be executed without user confirmation, the presence of the bypass mechanism in the documented interface makes accidental or policy-violating automation more likely.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
2. Confirm provisioning with user (present spec and estimated cost)
3. Execute: `bash <skill_dir>/scripts/provision_kunpeng_server.sh --confirm`
   - Creates VPC → Subnet → Security Group + SSH rule → EIP → ECS
   - Generates random root password, saves to `/tmp/kunpeng_server_env.sh` as `MIGRATE_SSH_PASS` (chmod 600)
4. Load env: `source /tmp/kunpeng_server_env.sh`
5. Verify SSH: `python <skill_dir>/scripts/ssh_client.py test`
6. Proceed to Task 1
Confidence
88% confidence
Finding
The provisioning flow creates a root account password, stores it in a temporary file, and then sources it into the environment for later SSH use. Even with chmod 600, persisting high-value credentials in /tmp and using root for automated remote operations materially increases exposure to credential theft, privilege escalation, and accidental full-system compromise.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
8. Adds SSH inbound rule (TCP 22, restricted to agent IP /32) via `hcloud VPC CreateSecurityGroupRule` with correct v3 API parameters (`--security_group_rule.security_group_id`, `--security_group_rule.direction`, `--security_group_rule.protocol`, `--security_group_rule.multiport`, `--security_group_rule.remote_ip_prefix`, `--security_group_rule.ethertype`, `--security_group_rule.action`, `--security_group_rule.priority`)
9. Finds Huawei Cloud EulerOS 2.0 Standard 64 bit for ARM image ID via `hcloud IMS ListImages --__imagetype=gold --__os_type=Linux` and filtering for "Standard 64 bit for ARM" (excluding BareMetal images)
10. Creates EIP via `hcloud EIP CreatePublicip --publicip.type=5_bgp --bandwidth.name=... --bandwidth.size=300 --bandwidth.charge_mode=traffic --bandwidth.share_type=PER`
11. Creates ECS instance with a randomly generated password (for cloud-init only) via `hcloud ECS CreateServers --cli-jsonInput=<temp-file>`. The full request body (including `server.adminPass`) is built in a temporary JSON file (mode 0600) and passed via `--cli-jsonInput` to avoid leaking the password via `ps -ef`. The temp file is securely deleted with `shred -u` after the call. **The password is saved to `/tmp/kunpeng_server_env.sh` as `MIGRATE_SSH_PASS` (chmod 600) for use by `ssh_client.py`.**
12. Waits for ECS job to reach SUCCESS status
13. Saves connection info (EIP address, port, user, instance ID, region, AND `MIGRATE_SSH_PASS`) to `/tmp/kunpeng_server_env.sh` (chmod 600)
Confidence
89% confidence
Finding
The provisioning flow stores the generated server password in '/tmp/kunpeng_server_env.sh' as an environment export, even though the file is chmod 600. Persisting a live SSH password in a predictable tmp-path increases the chance of credential theft through local compromise, backup/log mishandling, accidental sourcing, or residual-file exposure, especially because the file contains both host details and the authentication secret together.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
python <skill_dir>/scripts/ssh_client.py exec "sudo yum install -y python3 python3-pip curl" 60

# Ubuntu/Debian
python <skill_dir>/scripts/ssh_client.py exec "sudo apt-get update" 60
python <skill_dir>/scripts/ssh_client.py exec "sudo apt-get install -y python3 python3-pip curl" 60

# Then re-run with --skip-deps
Confidence
93% confidence
Finding
This line explicitly instructs the agent to run `sudo yum install -y ...` on the remote server, which performs privileged package installation without an explicit authorization checkpoint in the step itself. In an agent skill, automating sudo-backed changes increases the risk of unintended host modification, dependency changes, and impact to production systems if the target or context is wrong.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ubuntu/Debian
python <skill_dir>/scripts/ssh_client.py exec "sudo apt-get update" 60
python <skill_dir>/scripts/ssh_client.py exec "sudo apt-get install -y python3 python3-pip curl" 60

# Then re-run with --skip-deps
python <skill_dir>/scripts/ssh_client.py exec "bash /tmp/install_devkit.sh --yes --skip-deps" 300
Confidence
93% confidence
Finding
This line directs execution of `sudo apt-get update`, a privileged system-wide package metadata refresh, again without a mandatory confirmation step immediately before execution. Although common in administration, it is still a real vulnerability in an autonomous skill because it changes system state and can precede further package installation on a remote host.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Standard local install (with sudo, auto-detect version)
bash <skill_dir>/scripts/install_devkit.sh --yes

# Install without sudo (to ~/devkit)
bash <skill_dir>/scripts/install_devkit.sh --yes --no-sudo

# Install specific version
Confidence
89% confidence
Finding
This instruction promotes running an installation flow with elevated privileges, which can modify system packages and directories. While common for legitimate setup, it is still dangerous in an agent skill because the command could be executed on the analyst/agent host and grants broad system access to the referenced script.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
sudo yum install -y python3 python3-pip curl

# Ubuntu/Debian/UOS/Kylin
sudo apt-get update
sudo apt-get install -y python3 python3-pip curl

# SUSE
Confidence
90% confidence
Finding
The instruction tells the user/agent to run package installation commands with sudo, causing system-wide changes and trust in external repositories/packages. In an automated agent setting, this can unexpectedly alter the environment or be abused if the surrounding workflow executes without strong user consent.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ubuntu/Debian/UOS/Kylin
sudo apt-get update
sudo apt-get install -y python3 python3-pip curl

# SUSE
sudo zypper install -y python3 python3-pip curl
Confidence
90% confidence
Finding
Running apt-get update with sudo refreshes system package metadata and is a privileged system modification step. In isolation it is routine administration, but in a skill meant for automated use it still expands the blast radius of accidental execution and should be treated as a real safety concern.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
sudo apt-get install -y python3 python3-pip curl

# SUSE
sudo zypper install -y python3 python3-pip curl

# Then re-run with --skip-deps
bash <skill_dir>/scripts/install_devkit.sh --yes --skip-deps
Confidence
89% confidence
Finding
This sudo zypper install command performs system-wide package installation with administrative privileges. The danger comes from normalizing privileged execution in an agent skill without a clear consent boundary, making unintended host modification more likely.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
| 8 | (add rule) | `hcloud VPC CreateSecurityGroupRule` | `--security_group_rule.security_group_id=... --security_group_rule.direction=ingress --security_group_rule.protocol=tcp --security_group_rule.multiport=22 --security_group_rule.remote_ip_prefix=<AGENT_IP>/32 --security_group_rule.ethertype=IPv4 --security_group_rule.action=allow --security_group_rule.priority=1` |
| 9 | `get_image_id()` | `hcloud IMS ListImages` | `--__imagetype=gold --__os_type=Linux --limit=50`, then filters for "Standard 64 bit for ARM" excluding "BareMetal" |
| 10 | `create_eip()` | `hcloud EIP CreatePublicip` | `--publicip.type=5_bgp --bandwidth.name=kunpeng-devkit-bw --bandwidth.size=300 --bandwidth.charge_mode=traffic --bandwidth.share_type=PER` |
| 11 | `create_ecs()` | `hcloud ECS CreateServers --cli-jsonInput=<temp-file>` | Builds request body in a temporary JSON file. A random password is generated for cloud-init and saved to `/tmp/kunpeng_server_env.sh` as `MIGRATE_SSH_PASS` (chmod 600). Non-sensitive fields: `server.name=kunpeng-devkit-server`, `server.imageRef=...`, `server.flavorRef=kc1.2xlarge.2`, `server.vpcid=...`, `server.nics[0].subnet_id=...`, `server.publicip.id=...`, `server.root_volume.volumetype=GPSSD`, `server.root_volume.size=40`, `server.security_groups[0].id=...`, `server.availability_zone=cn-southwest-2a`. The temp file is securely deleted (`shred -u`) after use. |
| 12 | `wait_for_ecs()` | `hcloud ECS ShowJob` | Polls until job status = SUCCESS |
| 13 | `save_connection_info()` | Write to file | Saves `KUNPENG_SERVER_HOST`, `KUNPENG_SERVER_PORT`, `KUNPENG_SERVER_USER`, `KUNPENG_SERVER_ID`, `KUNPENG_SERVER_REGION`, AND `MIGRATE_SSH_PASS` to `/tmp/kunpeng_server_env.sh` (chmod 600) |
Confidence
76% confidence
Finding
The workflow stores a generated SSH password in /tmp/kunpeng_server_env.sh and then sources it for later remote access. Even with chmod 600, placing long-lived credentials in a predictable temporary-file location increases exposure to local compromise, accidental leakage, shell-history/process mistakes, or reuse by other local processes running as the same user.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- **Existing server path (Step 3c)**: No reminders needed — the user provided their own server. No SSH keys are injected and no ControlMaster sockets are left open (unified paramiko approach).
- **Local install path (Step 3a)**: No reminders needed — DevKit was installed locally.

The `provision_kunpeng_server.sh` script does NOT print any password rotation reminder — the password is saved only to `/tmp/kunpeng_server_env.sh` (chmod 600) and never output. The `ssh_client.py` script reads `MIGRATE_SSH_PASS` from `os.environ` (or Windows user-level registry as fallback) for each connection and wipes it immediately after connect. No SSH keys are injected, no ControlMaster sockets are left open.
Confidence
78% confidence
Finding
This repeats the design choice of keeping the server password in /tmp/kunpeng_server_env.sh and normalizes that behavior as acceptable operational practice. The issue is not chmod itself, but the persistence of a privileged remote-login secret in a temporary file that may survive longer than intended and be harvested on a compromised host.

Static analysis

No suspicious patterns detected.