T09 · Insecure Skill Coding Practices
- Location
scripts/ecommerce_ad_copy_generator.py:85- Finding
Fail-Open Billing Verification Permits Unpaid Content Generation
- Content
View full analysis
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: HighVulnerable 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
successproperty with a default value ofTrue:python response_data.get("success", True)Consequently, any HTTP response with a status below 300 is considered a successful charge when the response omits
successor cannot be parsed. The use ofbool(...)also accepts incorrectly typed truthy values. For example, the string"false"evaluates toTruein 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
- 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.
- The endpoint respond ...[truncated 1103 chars]
- Remediation
View remediation
Remediation Suggestions
- Make malformed, empty, or non-object JSON responses explicit billing failures rather than returning an empty dictionary.
- 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, )- Validate the complete response schema, including field types and required fields.
- Require a non-empty, correctly typed
transaction_idbefore allowing content generation. - Reject unexpected response content types and oversized response bodies.
- Treat all ambiguous conditions as billing failures and do not generate paid output unless the charge is positively verified.
- 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
- Enforce HTTPS for
SKILLPAY_CHARGE_ENDPOINTand preferably allowlist the expected billing host, especially when attachingSKILLPAY_API_KEY.
