Back to skill

Security audit

huawei-cloud-cloudrobo-infer

Security checks for vulnerabilities and agentic risk

Overview

The skill fits its CloudRobo management purpose, but its included test script can modify and delete a real inference service without a real confirmation prompt.

Review the verification script before running it. Do not set SERVICE_ID unless the target is disposable, and use least-privilege Huawei Cloud credentials. Treat downloaded model configuration as untrusted data and avoid storing or exposing AK/SK values in shared shells, scripts, CI logs, or persistent profiles.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/test-cli-commands.sh:76
Finding
Verification Script Performs Destructive Lifecycle Operations Without Explicit Confirmation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/test-cli-commands.sh`, lines 76–99 **Vulnerability Type**: Missing confirmation and unsafe destructive automation **Risk Level**: High ### Vulnerable Code ```bash if [ -n "$SERVICE_ID" ]; then echo "Test 4: Show service detail" cloudrobo infer show --service-id "$SERVICE_ID" echo "" echo "Test 5: Start service (user must confirm)" echo "WARNING: This starts the service, consuming pool resources. Press Ctrl+C to cancel." sleep 2 cloudrobo infer start --service-id "$SERVICE_ID" || echo "Start may fail if already running" echo "" echo "Test 6: Stop service (user must confirm)" echo "WARNING: This stops the service. Press Ctrl+C to cancel." sleep 2 cloudrobo infer stop --service-id "$SERVICE_ID" || echo "Stop may fail if already stopped" echo "" echo "Test 7: List logs (ms timestamps)" END_MS=$(date +%s%3N 2>/dev/null || echo "0") START_MS=$(( END_MS - 3600000 )) cloudrobo infer list-logs --service-id "$SERVICE_ID" --start-time "$START_MS" --end-time "$END_MS" --limit 50 || echo "Logs may be empty if service never ran" echo "" echo "Test 8: Update service (user must confirm)" echo "WARNING: This updates the service. Press Ctrl+C to cancel." sleep 2 cloudrobo infer update --service-id "$SERVICE_ID" --description "Updated by test" || echo "Update may fail" echo "" echo "Test 9: Delete service (user must confirm)" echo "WARNING: This deletes the service. Press Ctrl+C to cancel." sleep 2 cloudrobo infer delete --service-id "$SERVICE_ID" || echo "Delete may fail if service already gone" echo "" fi ``` ### Technical Analysis When the `SERVICE_ID` environment variable is non-empty, the verification script automatically performs four mutating operations: 1. Starts the selected inference service. 2. Stops the service. 3. Changes its description. 4. Permanently deletes the service. The messa ...[truncated 2104 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Make the script read-only by default. - Require an explicit option such as `--allow-mutations` before running any start, stop, update, or delete test. - Prompt separately before every mutating command and require an affirmative response. - For deletion, require the operator to type the exact service ID: ```bash read -r -p "Type the service ID to confirm deletion: " CONFIRM_ID if [ "$CONFIRM_ID" = "$SERVICE_ID" ]; then cloudrobo infer delete --service-id "$SERVICE_ID" else echo "Deletion cancelled." fi ``` - Use `--dry-run` where supported. - Do not treat a short sleep or “Press Ctrl+C” message as confirmation. - Display the workspace, service name, status, and service ID before requesting approval. - Separate destructive integration testing into a dedicated script intended only for disposable test services. - Require a marker or naming convention proving that the target is a test resource before deletion. ]]>

T08 · Insecure Dependencies

Warning
Location
references/cli-installation-guide.md:5
Finding
Unpinned Python Dependencies Are Installed From the Default Package Index<![CDATA[ ## Vulnerability Details **File Location**: `references/cli-installation-guide.md`, lines 5–19 **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash ### Option 1: Install all packages (recommended) ```bash pip install hw-cloudrobo-client ``` This installs the aggregate package with all functional modules (asset, dataset, train, eval, infer, robot, dispatch, workspace). ### Option 2: Install only infer package ```bash pip install hw-cloudrobo-infer ``` This installs `cloudrobo-core` (CLI framework) + `cloudrobo-infer`. ``` ### Technical Analysis The installation instructions request packages by name without specifying reviewed versions, artifact hashes, or an authoritative package index. Consequently, each installation resolves whatever release the configured Python package index currently considers appropriate. This prevents reproducible installation and creates exposure to: - Compromise of a future package release. - Compromise or misconfiguration of the selected package index. - Dependency confusion where an unintended package source has higher precedence. - Undetected changes in transitive dependencies. - Installation of a malicious source distribution or build backend. Python package installation may execute package-controlled build logic. Even when installation uses a wheel, the installed package runs later when the documented `cloudrobo` commands are invoked. ### Attack Path 1. An attacker compromises a named package, one of its transitive dependencies, or a package index used by the operator. 2. The attacker publishes a malicious version that satisfies the unconstrained package request. 3. A user follows the installation guide: ```bash pip install hw-cloudrobo-client ``` or: ```bash pip install hw-cloudrobo-infer ``` 4. Pip resolves and installs the attacker-controlled release. 5. Malicious build logic runs during installation, or malicious run ...[truncated 755 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin every direct dependency to a reviewed version, for example: ```bash python -m pip install "hw-cloudrobo-infer==<reviewed-version>" ``` - Publish a lock file or requirements file containing hashes and install it with: ```bash python -m pip install --require-hashes -r requirements.txt ``` - Document the authoritative package index and use `--index-url` where appropriate. - Audit and pin transitive dependencies. - Prefer signed release artifacts and document how users can verify signatures or checksums. - Recommend installation in an isolated virtual environment: ```bash python -m venv .venv . .venv/bin/activate python -m pip install --require-hashes -r requirements.txt ``` - Avoid running pip as root or through `sudo`. - Add dependency scanning and release-provenance verification to the publication process. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:161
Finding
Backend-Provided Download URL Is Fetched Without Destination or Resource Validation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 161–176 **Additional Location**: `references/service-config-catalog.md`, lines 124–137 **Vulnerability Type**: Unvalidated remote URL retrieval and unbounded response handling **Risk Level**: Medium ### Vulnerable Code ```python from cloudrobo_core.sdk import Config, HttpClient from cloudrobo_asset.client import AssetClient import requests config = Config() http = HttpClient(config) asset_client = AssetClient(http) resp = http.get( asset_client._url(f'/v1/assets/{asset_id}/versions/{version_id}/download-url'), params={'file_name': 'skill_config.json'} ) skill_config = requests.get(resp['file_url']).text ``` The same pattern is repeated in the service configuration reference: ```python resp = http.get( asset_client._url(f'/v1/assets/{asset_id}/versions/{version_id}/download-url'), params={'file_name': '<file_name>'} ) content = requests.get(resp['file_url']).text ``` ### Technical Analysis The authenticated CloudRobo API returns a dynamic `file_url`, which is then passed directly to `requests.get`. The documented implementation does not: - Require the URL scheme to be HTTPS. - Restrict the hostname to approved Huawei Cloud or object-storage domains. - Validate redirect destinations. - Configure connection and read timeouts. - Limit the response body size. - Call `raise_for_status()` before consuming the body. - Validate the downloaded data against the expected JSON or YAML schema before use. The `requests` library follows redirects by default. Therefore, control over the returned URL or its redirect chain can make the Agent host issue a GET request to an unexpected external or internal destination. Reading the entire response through `.text` also permits an unexpectedly large response to consume memory. The downloaded content is subsequently used to populate deployment settings such as skill prompts or model extension metadata. Malformed or attacker-controlled d ...[truncated 1860 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse the returned URL before requesting it. - Require `https` and reject URLs containing embedded user information. - Maintain an allowlist of expected Huawei Cloud or approved object-storage hostnames. - Resolve and reject loopback, link-local, private, multicast, and otherwise prohibited IP destinations where internal access is not required. - Disable redirects or validate every redirect destination: ```python response = requests.get( validated_url, timeout=(5, 30), allow_redirects=False, stream=True, ) response.raise_for_status() ``` - If redirects are necessary, follow them manually and reapply the same scheme, hostname, and IP validation at every hop. - Enforce an expected content type and a strict maximum download size while streaming. - Parse `skill_config.json` as JSON and validate its schema before use. - Parse model metadata using a safe YAML parser or strict JSON parser; reject unsupported object types and excessive nesting. - Treat downloaded prompts and configuration as untrusted data rather than Agent instructions. - Record the approved hostname and content digest for auditability without logging credentials or sensitive configuration values. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Vague Triggers

Medium
Confidence
78% confidence
Finding
The trigger list contains very broad terms such as 'infer', 'inference', and 'model deployment', which can cause the skill to activate in contexts not specifically intended for CloudRobo service management. Over-broad invocation increases the chance that a user request is routed into a skill capable of mutating cloud resources, including creating, starting, stopping, or deleting inference services.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The guide instructs users to place long-lived Huawei Cloud access key and secret key values directly into environment variables, but provides no warning about shell history, process inspection, CI/CD log leakage, or persistence in shared environments. In a cloud-management skill that can create, start, stop, and delete inference services, exposed AK/SK credentials could enable unauthorized control over cloud resources and access to service data.

Static analysis

No suspicious patterns detected.