Back to skill

Security audit

huawei-cloud-voucher-send

Security checks for vulnerabilities and agentic risk

Overview

This coupon-issuing skill needs review because gaps in its financial safeguards can permit duplicate issuance or unintended credential selection.

Have the duplicate-protection and credential-selection defects corrected before live use. Verify the active account, quota, recipients, and amount; use narrowly scoped credentials and preview each batch. Avoid direct CLI issuance, concurrent runs, and --force, and reconcile uncertain outcomes with Huawei before retrying. Keep the ledger in a private directory.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (10)

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented design records successful issuance in a local ledger after the remote money-moving operation, leaving a crash or persistence-failure window in which a retry can issue another coupon; a local ledger alone cannot guarantee the advertised no-double-issue property. The static report additionally identifies missing concurrency protection and an operation guard enforced only in main(), although those implementation details cannot be independently verified without the scripts. Irreversible financial effects make these reliability and boundary-enforcement gaps security-relevant.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The API operation and target resources match the declared coupon-issuance purpose. However, the supplied executable command directly performs that irreversible operation without the safety controls described as mandatory defaults. This is a material behavioral mismatch, not an unrelated capability or a permissions discrepancy. Other advertised features absent from this small chunk are not independently treated as mismatches.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
70% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/config.py (reported line 35)May include surrounding context.

python
Only variables prefixed with HUAWEI / HW_ / HWC are considered, so arbitrary
    environment entries can never be mistaken for credentials.
    """
    for key, value in os.environ.items():
        upper = key.upper()
        if not upper.startswith(_CREDENTIAL_PREFIXES):
            continue

Using --force discards unrelated issuance records, allowing subsequent retries to double-issue coupons.

High
Category
Excessive Agency
Confidence
99% confidence
Finding

With force=True, the existing ledger is not loaded, leaving ledger initialized to an empty dictionary. The later save replaces the ledger with only the current call's recorded successes, erasing unrelated issuance records and allowing subsequent ordinary retries to issue those customers additional irreversible financial benefits.

Content

No source excerpt is available for this finding.

The issue-only operation guard is enforced by main(), but bypassed by the callable send_coupons() execution path.

High
Category
Excessive Agency
Confidence
97% confidence
Finding

The command-line entry point validates the operation, but send_coupons accepts an arbitrary operation and passes it into the live hcloud command without enforcing the issue-only restriction. A direct Python caller can therefore attempt another BSS operation under the active credentials, although successful execution depends on that operation accepting the constructed arguments; the confirmation requirement still applies.

Content

No source excerpt is available for this finding.

Skill declares no tool scope ('permissions' or 'allowed-tools') but code capabilities were detected: env, file_write, network, shell.

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Credential discovery accepts nonstandard environment variables despite the manifest's standard-variable-only restriction.

Medium
Category
Excessive Agency
Confidence
98% confidence
Finding

Credential selection uses broad prefix and substring matches rather than documented variable names, so unrelated or nonstandard variables can take precedence based on environment iteration order. AK and SK are selected independently, potentially mixing credential pairs or selecting an unintended account; the money-moving SDK fallback makes valid but unintended credential selection more consequential, although exploitation requires influence over the environment or conflicting existing variables.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/send_voucher.py (reported line 261)May include surrounding context.

python
cmd.extend(extra)
    cmd.extend(argv)
    try:
        proc = subprocess.run(
            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
            timeout=120, universal_newlines=True,
        )

Tainted flow: 'cmd' from os.environ.get (line 255, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/send_voucher.py (reported line 261)May include surrounding context.

python
cmd.extend(extra)
    cmd.extend(argv)
    try:
        proc = subprocess.run(
            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
            timeout=120, universal_newlines=True,
        )

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

Medium
Category
Data Flow
Confidence
83% confidence
Finding

The security issue is the predictable temporary filename opened with ordinary write mode, rather than environment-derived paths alone. If the ledger is placed in a directory writable by an attacker, the attacker can pre-create ledger.json.tmp as a symlink and cause a file writable by the executing account to be truncated and overwritten; the default private-account cache location reduces exposure.

Content

Scanner excerpt · scripts/send_voucher.py (reported line 475)May include surrounding context.

python
if directory:
            os.makedirs(directory, exist_ok=True)
        tmp = path + ".tmp"
        with open(tmp, "w", encoding="utf-8") as handle:
            json.dump({"entries": entries}, handle, ensure_ascii=False, indent=2)
        os.replace(tmp, path)
    except OSError:

Static analysis

No suspicious patterns detected.