T09 · Insecure Skill Coding Practices
- Location
handler.py:439- Finding
Payment Authorization Bypass Through Unvalidated payment_proof Presence Check
- Content
View full analysis
0 and "payment_proof" not in request: amount, currency, details = self._calculate_payment(capability, params) logger.info(f"[Brand A] Payment required: {amount} {currency}") return payment_required_response(amount, currency, details) # Security gateway approved, denial_reason, security_details = self._wrap_security(request) if not approved: logger.warning(f"[Brand A] Security denied: {denial_reason}") return error_response(403, f"Security check failed: {denial_reason}") # Route to handler with translation result = self._route_capability(capability, params) if security_details: result["security"] = _translate_response_b_to_a(security_details) return result ``` The security wrapper constructs its request without including the payment proof: ```python security_request = SecurityRequest( interface="openclaw_skill_brand_a", operation=brand_b_capability, agent_id=agent_id, parameters=_translate_params_a_to_b(params), amount_sats=params.get("stake_units", params.get("transfer_units", 0)), security_level=security_level, metadata={"request_id": request.get("id", "unknown"), "brand": "A"}, ) ``` ### Technical Analysis The paid-capability gate verifies only that the `payment_proof` key exists in the request. It does not validate the value's type, signature, payer, recipient, amount, asset, network, confirmation state, expiration, nonce, or replay status. Consequently, values such as `null`, an empty object, an arbitrary string, or a forged structure satisfy the local authorization condition. The proof is not passed into `_wrap_security()` and `_route_capability()` forwards only the translated capability paramete ...[truncated 1362 chars]- Remediation
View remediation
