Back to skill

Security audit

huawei-cloud-optv-solver-assistant

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated Huawei OptVerse automation purpose, but it handles cloud credentials, confirmations, downloads, and TLS in ways that need careful Review before installation.

Install only after reviewing these risks. Use a least-privilege Huawei Cloud account and a non-sensitive project, avoid shared machines, do not use --auto-confirm/--deploy/--test unless you explicitly want those actions, and fix TLS verification, token storage permissions, filename sanitization, and fail-closed confirmations before production use.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create_chat.py:489
Finding

TLS Certificate Verification Disabled for Authenticated Cloud Requests

Content
View full analysis

Vulnerability Details

File Location: scripts/create_chat.py:59, 489-501; scripts/run_workflow.py:50, 193-199, 253-257, 532-536, 763-771
Vulnerability Type: Improper Certificate Validation
Risk Level: High

Complete Code Snippet

python
# scripts/create_chat.py
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

resp = requests.post(
    url,
    data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
    headers=headers,
    stream=True,
    verify=False,
    timeout=300,
    proxies={"http": None, "https": None},
)
python
# scripts/run_workflow.py
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

resp = requests.post(
    url,
    data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
    headers=headers, stream=True, verify=False, timeout=300,
    proxies={"http": None, "https": None},
)

resp = requests.get(
    url, headers=headers, verify=False, timeout=60,
    proxies={"http": None, "https": None},
)

resp = requests.get(
    url, verify=False, timeout=120,
    proxies={"http": None, "https": None},
)

Technical Analysis

The scripts explicitly pass verify=False to Requests and suppress the resulting insecure-request warnings. Encryption remains in use, but the client does not authenticate the server certificate. Consequently, any certificate presented by an intermediary is accepted.

The affected authenticated requests include the OptVerse SSE conversation endpoint, artifact downloads, model-service test artifact retrieval, and downloads from URLs returned in task results. OptVerse requests carry the live IAM token in the X-Auth-Token header and process user files, chat content, model requests, and generated artifacts.

This is a reachable defect during normal Skill operation and does not require malformed user input.

Attack Path

  1. The user invokes create_chat.py or `run_workflo ...[truncated 1132 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove every verify=False argument and restore Requests' default certificate validation.
  • Remove global suppression of InsecureRequestWarning.
  • If the service requires a private certificate authority, accept a trusted CA bundle through explicit configuration and pass its path through verify="/path/to/ca-bundle.pem".
  • Do not provide an unrestricted option that silently disables verification. If a diagnostic override is unavoidable, require explicit user authorization, emit a prominent warning, and prohibit sending credentials while it is enabled.
  • Validate that redirects cannot forward authenticated requests to unrelated hosts.
  • Rotate IAM tokens that may have been transmitted through an unverified connection.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/create_chat.py:84
Finding

IAM Token Persisted in a Predictable Shared Temporary File Without Enforced Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/create_chat.py:84-88, 133-159, 360-366
Vulnerability Type: Insecure Temporary File and Plaintext Credential Storage
Risk Level: Medium

Complete Code Snippet

python
# Persisted token cache (temp dir only, survives process restarts, 23h validity)
TOKEN_FILE = os.path.join(
    os.environ.get("TEMP", "/tmp"), "optverse_iam_token.txt"
)

def _load_cached_token(region):
    try:
        with open(TOKEN_FILE, "r", encoding="utf-8") as f:
            lines = f.read().splitlines()
        if len(lines) >= 3:
            ts = float(lines[0])
            cached_region = lines[1]
            token = "\n".join(lines[2:])
            if cached_region == region and time.time() - ts < 23 * 3600 and token:
                return token
    except (OSError, IOError, ValueError):
        print(f"[WARN] Failed to load cached token", file=sys.stderr)
    return None

def _save_token(token, region):
    """Persist the IAM token to the temp-file cache (temp dir only)."""
    try:
        with open(TOKEN_FILE, "w", encoding="utf-8") as f:
            f.write(f"{time.time()}\n{region}\n{token}\n")
    except (OSError, IOError):
        print(f"[WARN] Failed to save token cache", file=sys.stderr)
python
_token_cache["token"] = token
_token_cache["timestamp"] = time.time()
_token_cache["region"] = region
_save_token(token, region)

Technical Analysis

A successful authentication stores the complete IAM token in a fixed filename under TEMP or /tmp. The file is opened with ordinary "w" mode. The implementation does not:

  • Create a private per-user directory.
  • Enforce owner-only permissions such as 0600.
  • Use exclusive or atomic creation.
  • Reject symbolic links.
  • Verify file ownership or file type before reading and writing.
  • Remove the cache immediately after use.

The token remains reusable for up to 2 ...[truncated 1330 chars]

Remediation
View remediation

Remediation Suggestions

  • Prefer process-memory caching or an operating-system credential store instead of plaintext token persistence.
  • If cross-process persistence is necessary, create a per-user cache directory with owner-only permissions.
  • Create the token file atomically with restrictive mode 0600.
  • Use no-follow and exclusive-creation semantics where supported.
  • Validate that the cache is a regular file owned by the current user before reading or replacing it.
  • Use a randomized per-user filename rather than a global fixed path.
  • Delete expired tokens securely and provide a logout or cache-clear operation.
  • Update SKILL.md and references/best-practices.md so their storage claims accurately match the implementation.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_workflow.py:243
Finding

Remote Artifact Filename Allows Filesystem Path Traversal

Content
View full analysis

Vulnerability Details

File Location: scripts/run_workflow.py:243-275
Vulnerability Type: Path Traversal and Arbitrary File Overwrite
Risk Level: High

Complete Code Snippet

python
def download_file(token, route_id, chat_id, filename):
    """DownloadFile → saves to ARTIFACTS_DIR, returns saved path."""
    from urllib.parse import quote

    encoded = quote(filename, safe="")
    url = f"https://{ENDPOINT}/v1/{PROJECT_ID}/chats/{chat_id}/file/{encoded}/download"
    headers = {
        "X-Auth-Token": token,
        "X-Chat-Route-Id": route_id,
        "X-Need-Content": "true",
    }
    resp = requests.get(
        url, headers=headers, verify=False, timeout=60,
        proxies={"http": None, "https": None},
    )
    if resp.status_code != 200:
        print(f"  [DownloadFile] {filename} → ERROR {resp.status_code}")
        return None

    os.makedirs(ARTIFACTS_DIR, exist_ok=True)
    save_path = os.path.join(ARTIFACTS_DIR, filename)

    # Response JSON has content field that is base64-encoded
    ct = resp.headers.get("Content-Type", "")
    if "json" in ct:
        try:
            raw = resp.json().get("content", "")
            if raw:
                content_bytes = base64.b64decode(raw)
                with open(save_path, "wb") as f:
                    f.write(content_bytes)
                print(f"  [DownloadFile] {filename} → {save_path} ({len(content_bytes)} bytes)")
                return save_path
        except Exception:
            print(f"  [WARN] Failed to decode base64 content for {filename}", file=sys.stderr)

    with open(save_path, "wb") as f:
        f.write(resp.content)

Technical Analysis

filename originates from remote SSE type=file events and is passed directly to download_file(). URL encoding protects the HTTP path but does not make the value safe for local filesystem use.

The local destination is formed ...[truncated 1574 chars]

Remediation
View remediation

Remediation Suggestions

  • Treat every remote filename as untrusted.
  • Reject empty names, absolute paths, .. components, path separators, NUL characters, Windows drive prefixes, and UNC paths.
  • Prefer reducing the remote name to a validated basename.
  • Resolve both the artifact root and candidate destination and verify that the destination is a child of the artifact root before opening it.
  • Create destination files with exclusive semantics when overwriting is not explicitly required.
  • Apply the same validation to OBS result names and every other remote-to-local download path.
  • Add tests covering POSIX traversal, Windows traversal, absolute paths, encoded separators, and symbolic-link destinations.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run_workflow.py:570
Finding

End-of-File on Standard Input Silently Bypasses Explicit Confirmation

Content
View full analysis

Vulnerability Details

File Location: scripts/run_workflow.py:570-585; confirmation use sites at 616-618, 633-635, 661-663, 686-688, 723, 751
Vulnerability Type: Fail-Open Authorization and Confirmation Bypass
Risk Level: Medium

Complete Code Snippet

python
def wait_for_user_confirm(message):
    """Print a confirmation prompt and wait for user input."""
    print(f"\n{'='*60}")
    print(f"  ⏸  {message}")
    print(f"  Type 'yes' to continue, 'no' to abort:")
    print(f"{'='*60}")
    while True:
        try:
            answer = input().strip().lower()
        except EOFError:
            answer = "yes"  # non-interactive mode
        if answer in ("yes", "y", "确认"):
            return True
        if answer in ("no", "n", "取消"):
            return False
        print("Please type 'yes' or 'no':")
python
if not auto_confirm:
    if not wait_for_user_confirm(
        "Review solver results. Continue to publish?"
    ):
        print("[ABORTED] User cancelled.")
        sys.exit(0)

pub_id = publish_chat(
    chat_id, publish_name, "optverse", publish_description
)

Technical Analysis

The confirmation function treats EOFError as an affirmative response. An EOF is common when an agent, scheduler, CI job, detached process, or other automation invokes the script without an interactive standard input stream.

This means the code does not require the documented --auto-confirm flag to authorize non-interactive progression. Instead, the absence of a response is converted into approval. The affected gates cover transitions between workflow stages and the confirmation immediately preceding publication. Deployment and test operations also use this confirmation helper after their corresponding options have been selected.

The implementation therefore fails open at an authorization boundary that the Skill documentation describes as requiring explicit u ...[truncated 1162 chars]

Remediation
View remediation

Remediation Suggestions

  • Treat EOFError as denial and terminate without performing the pending action.
  • Require the explicit --auto-confirm flag for non-interactive execution.
  • Consider separate flags for stage progression, publication, deployment, and test execution rather than one broad authorization.
  • Detect non-interactive standard input before starting and fail with a clear message unless the necessary explicit authorization flags are present.
  • Record which explicit option authorized each consequential cloud operation.
  • Add automated tests proving that EOF, empty input, malformed input, and interrupted input cannot authorize publication or deployment.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (74)

Tainted flow: 'dl_url' from os.environ.get (line 764, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/run_workflow.py (reported line 765)May include surrounding context.

python
from urllib.parse import quote
                encoded = quote(json_fname, safe="")
                dl_url = f"https://{ENDPOINT}/v1/{PROJECT_ID}/chats/{chat_id}/file/{encoded}/download"
                dl_resp = requests.get(
                    dl_url,
                    headers={"X-Auth-Token": token, "X-Chat-Route-Id": route_id,
                              "X-Need-Content": "true"},

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The document claims the IAM token is cached 'in-memory only' and 'never persisted to disk', but elsewhere states it is stored in a temp file for cross-process reuse for 23 hours. This is a material security contradiction because operators may rely on a false guarantee and underestimate token exposure, while temp-file token persistence expands the attack surface to local file theft or reuse by other processes.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documents extensive capabilities—shell, file access, network calls, environment use, uploads/downloads, deployment, and testing—but does not declare an explicit tool scope or allowlist. That creates an authorization ambiguity where an agent may invoke more tools than intended, increasing the blast radius if the workflow is triggered incorrectly or manipulated by prompt input.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger list includes generic phrases such as “决策引擎”, “需求分析建模”, and “模型发布”, which are broad enough to match common discussion about optimization workflows rather than a clear invocation of this specific skill. The document also does not provide exclusion conditions or negative examples to clarify when these phrases should not activate the skill.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The skill relies on persisted local state for credentials and chat/session continuity, and the documented workflow emphasizes reusing route IDs, chat IDs, and a credentials file. Even though it tries to minimize exposure, this creates session persistence and secret-handling risk: local artifacts or state may be reused unintentionally, accessed by other processes, or lead the agent to act in an existing session context without sufficient revalidation.

Content

Scanner excerpt · SKILL.md (reported line 79)May include surrounding context.

md
>
> The agent **MUST NEVER** use `Read`, `Bash` (`cat`, `Get-Content`, `type`), `Write`, or any other tool to open, display, inspect, or clear the credentials file (`~/.config/optverse/credentials`). **Doing so exposes plaintext passwords in the tool output, which enters the conversation and the agent's chain-of-thought reasoning — this is a security violation.**
>
> The scripts handle everything automatically: auto-create template, read values in-process, clear values unconditionally. The agent only needs to **run the script** — never read the file.
>
> To check if credentials are filled, use the safe check command (outputs only `FILLED` or `EMPTY`, never values):
> ```bash

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The capability-boundaries section says certain management/deployment-style operations are unsupported, but later sections explicitly document deployment and testing steps via CreateModelService, ShowModelServiceDetail, and CreateModelServiceTask. This contradiction can mislead downstream agents or reviewers and may cause policy bypass, where risky actions are performed under the assumption they are out of scope.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
89% confidence
Finding

The presence of an auto-confirm capability enables the agent to proceed through sensitive workflow stages without human review. In this skill, that matters because later steps publish assets and can deploy/test services, so skipped checkpoints materially increase the chance of unintended changes or data handling errors.

Content

Scanner excerpt · SKILL.md (reported line 252)May include surrounding context.

--test

text

Use `--auto-confirm` to skip user confirmation prompts.
Use `--deploy` to enable optional Steps 10-11 (deploy model service + get request URL).
Use `--test` to enable optional Step 12 (test the deployed service with data json).

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
89% confidence
Finding

The presence of an auto-confirm capability enables the agent to proceed through sensitive workflow stages without human review. In this skill, that matters because later steps publish assets and can deploy/test services, so skipped checkpoints materially increase the chance of unintended changes or data handling errors.

Content

Scanner excerpt · SKILL.md (reported line 252)May include surrounding context.

--test

text

Use `--auto-confirm` to skip user confirmation prompts.
Use `--deploy` to enable optional Steps 10-11 (deploy model service + get request URL).
Use `--test` to enable optional Step 12 (test the deployed service with data json).

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill includes optional deployment and remote test operations that can create live services and send requests to them, but it does not pair those actions with a clear user-facing warning about external side effects, resource creation, potential cost, or environment impact. In an agent setting, that omission raises the risk of unintended infrastructure changes or billable actions being performed too casually.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The workflow directs users to upload requirement and data files to a remote cloud service and later publish generated outputs, but it does not clearly disclose these transmission and publication effects at the point of action. This can lead to unintentional exposure of sensitive business data, optimization inputs, or proprietary model artifacts, especially in enterprise planning contexts.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The workflow advances important stages using the generic message "确认" without binding that approval to a specific artifact set, checksum, stage, or explicit action. In a multi-step cloud workflow that uploads files, generates artifacts, and eventually publishes assets, this creates approval ambiguity and raises the risk of unintended progression, social engineering, or approval of altered outputs.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This step again uses a vague "确认" token to advance the workflow after artifact generation, with no explicit statement of what is being approved or whether the user reviewed the outputs. Because the system interacts with a remote decision engine and generated model artifacts, ambiguous approval can cause accidental acceptance of incorrect or manipulated modeling results.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Using the same ambiguous confirmation before the finalization phase is more serious because the next step leads to downloading final artifacts and publishing the chat as an asset. A generic approval word increases the chance that users authorize publication without clearly understanding that a remote publish action will occur.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The acceptance criteria require --cli-region=cn-north-7 in every listed hcloud command, and the parameter table later marks cn-north-7 as the only valid value. This imposes a fixed locale/region behavior in natural-language guidance without any opt-in or explanation that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
70% 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.

Content

Scanner excerpt · references/acceptance-criteria.md (reported line 95)May include surrounding context.

md
| AK/SK exposure | Never in stdout, logs, or reports | AK/SK visible in any output |
| AK/SK in conversation | Never asked user to type AK/SK in chat | User prompted for plaintext credentials |
| Sensitive value in reasoning | Token/credentials never appear in agent output, tool output, or chain-of-thought | Any sensitive value echoed or read via tools |
| File permissions | Script not world-readable | Script readable by all users |
| Debug output | AK masked as `XXXX****XXX` | Full AK/SK in debug output |

## 5. Workflow Validation

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file instructs use of a Python script for SSE chat requests and documents file upload/download operations, which can transmit user-provided messages, filenames, and file contents to a remote service. The reference is purely operational and does not include any warning that these actions send data off-system or may expose conversation history and attached files to the service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file instructs the agent to use specific Chinese phrases such as "确认" and to communicate only in business language, while forbidding technical wording. This imposes a language/locale style on user interactions without any user opt-in or alternative language choice, which matches the natural-language policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This instruction says to always use business language and provides only Chinese example phrases, while prohibiting technical details in user-facing responses. Because it mandates a specific communication language/style without offering the user a choice or documenting a justified locale restriction, it is a policy violation under SQP-3.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The guide has users configure AK/SK and then run a command that lists configured profiles, including a partially revealed access key ID, without a clear warning about handling sensitive output. In an agent-assisted or shared-terminal context, this can expose credentials or metadata in logs, screenshots, chat transcripts, or shell history and increase the chance of secret leakage.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The guide instructs users to place an IAM password in a local plaintext credentials file while simultaneously claiming the values are 'never persisted.' That claim is misleading because the password is explicitly persisted at rest on disk, creating a credential exposure risk through local compromise, backups, indexing, or accidental disclosure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The workflow requires the user to send the Chinese phrase "确认" and also uses the Chinese command "进行数据检查" as fixed interaction messages. This imposes a specific language on users without any opt-in or documented locale justification, which is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Allowing SSL verification to be disabled weakens transport security and can enable man-in-the-middle interception or tampering of requests to the OptVerse service. In this skill, those requests may carry AK/SK-signed traffic, conversation state, uploaded files, and solver outputs, so bypassing certificate validation materially increases exposure.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation states credentials are never persisted, but the code deliberately persists an IAM token in a temp file for 23 hours. This mismatch can cause operators to underestimate exposure and leave sensitive bearer tokens on disk where local compromise, backup leakage, or accidental disclosure could occur.

Content

No source excerpt is available for this finding.

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

Medium
Category
Data Flow
Confidence
95% confidence
Finding

The IAM token is written to a path derived from the TEMP environment variable without enforcing secure file ownership, permissions, or symlink safety. A local attacker who can influence TEMP or pre-place links/files in that location could redirect token storage, steal the token, or overwrite arbitrary files accessible to the process.

Content

Scanner excerpt · scripts/create_chat.py (reported line 156)May include surrounding context.

python
def _save_token(token, region):
    """Persist the IAM token to the temp-file cache (temp dir only)."""
    try:
        with open(TOKEN_FILE, "w", encoding="utf-8") as f:
            f.write(f"{time.time()}\n{region}\n{token}\n")
    except (OSError, IOError):
        print(f"[WARN] Failed to save token cache", file=sys.stderr)

Session Persistence

Medium
Category
Rogue Agent
Confidence
78% confidence
Finding

The design intentionally relies on a persistent local credentials file and a long-lived token cache to support multi-round sessions. In a skill that handles cloud IAM authentication, local session persistence increases the attack surface for credential mishandling, local file disclosure, and unintended reuse across runs.

Content

Scanner excerpt · scripts/create_chat.py (reported line 163)May include surrounding context.

python
def _ensure_credentials_file():
    """Create the credentials file template if it does not exist.

    Contains only empty keys (no sensitive data) so the user just fills in
    the values. Called on every run so the file is always available.

Static analysis

Detected: suspicious.insecure_tls_verification

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
scripts/create_chat.py:495

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
scripts/run_workflow.py:197