Back to skill

Security audit

Ecommerce Ad Copy Generator

Security checks for vulnerabilities and agentic risk

Overview

The skill broadly matches its advertised ad-copy purpose, but its billing check can approve paid generation without verified payment and its billing endpoint/token handling is under-scoped.

Review before installing in any paid workflow. The skill should fail closed on billing responses, require an explicit successful boolean and transaction id, and restrict the billing endpoint before using SKILLPAY_API_KEY. Expect Chinese-only generated copy unless the publisher adds locale controls or documents that scope clearly.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ecommerce_ad_copy_generator.py:85
Finding
Fail-Open Billing Verification Permits Unpaid Content Generation## Vulnerability Details **File Location**: `scripts/ecommerce_ad_copy_generator.py`, lines 85-92 and 145-158 **Vulnerability Type**: Fail-open validation of billing API responses **Risk Level**: High ### Vulnerable Code ```python def _safe_json_load(raw: bytes) -> dict[str, Any]: if not raw: return {} try: return json.loads(raw.decode("utf-8")) except (UnicodeDecodeError, json.JSONDecodeError): return {} ``` ```python with request.urlopen(req, timeout=self.timeout_seconds) as response: response_data = _safe_json_load(response.read()) status = getattr(response, "status", 200) success = bool(response_data.get("success", True)) and status < 300 return ChargeResult( success=success, transaction_id=str(response_data.get("transaction_id", "")) or None, payment_url=_normalize_payment_url(response_data, user_id), status_code=status, error_code=None if success else _extract_error_code(response_data), raw_response=response_data, ) ``` ### Technical Analysis The billing response parser converts an empty response body, invalid UTF-8, or malformed JSON into an empty dictionary. The success check then reads the `success` property with a default value of `True`: ```python response_data.get("success", True) ``` Consequently, any HTTP response with a status below 300 is considered a successful charge when the response omits `success` or cannot be parsed. The use of `bool(...)` also accepts incorrectly typed truthy values. For example, the string `"false"` evaluates to `True` in Python. No valid transaction identifier is required before paid content is generated. This violates the fail-closed behavior expected for a billing authorization boundary. ### Attack Path 1. An attacker influences the configured billing endpoint, an intermediary proxy, or a mock billing service, or takes advantage of a billing service returning an unexpected response. 2. The endpoint respond ...[truncated 1103 chars]
Remediation
## Remediation Suggestions 1. Make malformed, empty, or non-object JSON responses explicit billing failures rather than returning an empty dictionary. 2. Require an exact Boolean success value: ```python if response_data.get("success") is not True: return ChargeResult( success=False, status_code=status, error_code=_extract_error_code(response_data), raw_response=response_data, ) ``` 3. Validate the complete response schema, including field types and required fields. 4. Require a non-empty, correctly typed `transaction_id` before allowing content generation. 5. Reject unexpected response content types and oversized response bodies. 6. Treat all ambiguous conditions as billing failures and do not generate paid output unless the charge is positively verified. 7. Add tests covering: - Empty HTTP 200 responses - Malformed JSON in HTTP 200 responses - `{}` in HTTP 200 responses - Missing `success` - `"success": "false"` - `"success": 1` - Successful responses without a transaction ID 8. Enforce HTTPS for `SKILLPAY_CHARGE_ENDPOINT` and preferably allowlist the expected billing host, especially when attaching `SKILLPAY_API_KEY`.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill advertises network, environment-variable, and file access behavior but does not declare any explicit tool scope such as allowed-tools or permissions. That mismatch weakens sandboxing and review controls, because an execution environment may grant broader capabilities than a user or orchestrator expects, including outbound billing calls and access to secrets in environment variables.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This Python skill generates ad copy entirely in Chinese and also returns Chinese billing error text, but nowhere in the file does it let the user opt into that locale or indicate that the skill is intentionally region-specific. That creates a natural-language policy issue because the skill forces a specific language for both content and user-facing messages.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The test payloads and assertions hard-code Chinese product data, audience text, and later verify a Chinese-only error message ("余额不足"). This indicates the skill behavior may be tied to a specific language/locale without user opt-in or an explicit documented regional justification, which matches the language/locale policy concern.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The test explicitly requires the exception string to contain the Chinese phrase "余额不足", which codifies a single-language response. Without a documented opt-in or justified region-specific scope, this is a natural-language locale policy issue.

Static analysis

No suspicious patterns detected.