T09 · Insecure Skill Coding Practices
- Location
- scripts/service.py:35
- Finding
- Payment Authorization Can Be Forged Through Local Order-File Modification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/service.py:35-61` **Vulnerability Type**: Improper payment credential validation and fail-open authorization **Risk Level**: High ### Vulnerable Code ```python def is_credential_valid(order_data: dict) -> bool: credential = order_data.get("payCredential") if not credential: return False ts = order_data.get("credentialTimestamp") if ts and time.time() - ts > CREDENTIAL_TTL: return False return True if __name__ == "__main__": parser = argparse.ArgumentParser(description="Verify payment and authorize video creation service") parser.add_argument("order_no", help="Order number from Phase 1") args = parser.parse_args(); indicator = compute_indicator(SLUG) try: order_data = _load_order(indicator, args.order_no) except Exception as e: print("PAY_STATUS: ERROR"); print(f"ERROR_INFO: Order file read failed: {e}"); sys.exit(1) if not is_credential_valid(order_data): print("PAY_STATUS: ERROR") print("ERROR_INFO: No valid payment credential found. Complete payment via clawtip first.") sys.exit(1) pay_status = order_data.get("payStatus", "SUCCESS") print(f"PAY_STATUS: {pay_status}") if pay_status != "SUCCESS": print(f"ERROR_INFO: Payment status is '{pay_status}', cannot proceed"); sys.exit(1) ``` ### Technical Analysis Payment authorization is based entirely on fields loaded from a JSON file located in the current user's home directory. That file is writable by the same user who invokes the service. The `is_credential_valid` function only verifies that `payCredential` contains a truthy value. It does not verify a digital signature, message authentication code, trusted issuer, order number, amount, recipient, or skill identifier. The timestamp check is also optional. If `credentialTimestamp` is absent, credential expiration is not enforced. In addition, `payStatus` defaults to `SUCCESS` when it is missing, cau ...[truncated 1249 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Replace trust in editable JSON fields with a cryptographically authenticated payment credential. - Require the payment service to issue a digitally signed token or a MAC-protected receipt using a key unavailable to the local user. - Verify all security-relevant claims, including: - Trusted issuer - Order number - Exact amount - Payment recipient - Skill identifier - Explicit successful payment status - Issuance and expiration timestamps - Require `credentialTimestamp` and reject missing, malformed, future-dated, or expired timestamps. - Remove the `SUCCESS` default: ```python pay_status = order_data.get("payStatus") if pay_status != "SUCCESS": reject_payment() ``` - Bind the authenticated credential to the local order and reject mismatched order numbers or amounts. - Where possible, query the trusted payment service directly and verify the response over authenticated TLS. - Add tests proving that fabricated credentials, missing timestamps, missing statuses, modified amounts, and replayed credentials are rejected. ]]>
