T09 · Insecure Skill Coding Practices
- Location
- scripts/ccs_online_client.py:82
- Finding
- Custom online endpoints permit plaintext transmission of receipts and authentication credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ccs_online_client.py:48-49, 82-107`; invocation at `scripts/verify_receipt_online.py:132-136` **Vulnerability Type**: Failure to enforce secure transport for sensitive network requests **Risk Level**: High ### Vulnerable Code ```python def resolve_endpoint(cli_value: str | None = None) -> str: ep = cli_value or os.environ.get("CCS_API_ENDPOINT") or DEFAULT_ENDPOINT return ep.rstrip("/") ``` ```python def call(path: str, body: dict, endpoint: str | None = None, timeout: float = 30.0) -> dict: """POST JSON to the CCS API; return the parsed JSON response. Raises PaymentRequiredError on HTTP 402 (bill printed to stderr), CCSAPIError on other non-2xx. The request body is never logged. """ ep = resolve_endpoint(endpoint) data = json.dumps(body, ensure_ascii=False).encode("utf-8") if len(data) > MAX_BODY_BYTES: raise CCSAPIError(413, {"error": f"Request body exceeds {MAX_BODY_BYTES} byte limit"}) headers = {"Content-Type": "application/json; charset=utf-8", "User-Agent": "CCS-CLI/1.0 (channel=clawhub)"} api_key = os.environ.get("CCS_API_TOKEN") if api_key: headers["X-API-Key"] = api_key proof = os.environ.get("CCS_PAYMENT_PROOF") or os.environ.get("CCS_PAY_TOKEN") if proof: headers["Payment-Proof"] = proof req = urllib.request.Request(ep + path, data=data, headers=headers, method="POST") try: with urllib.request.urlopen(req, timeout=timeout) as r: return json.loads(r.read().decode("utf-8")) ``` The request is initiated by: ```python rep = client.call("/v1/verify/receipt", {"receipt": receipt, "public_key_pem": pub_pem}, endpoint=args.endpoint) ``` ### Technical Analysis The endpoint can be overridden through the `--endpoint` command-line argument or the `CCS_API_ENDPOINT` environment variable. `resol ...[truncated 2428 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse endpoints with `urllib.parse.urlsplit()` and reject malformed URLs. 2. Require the `https` scheme for all remote endpoints. 3. If local development requires HTTP, permit it only for verified loopback addresses behind a separate explicit option such as `--allow-insecure-localhost`. 4. Maintain a trusted-host allowlist for the hosted service. Require explicit user confirmation before transmitting data to any custom host. 5. Reject URLs containing user-information components, ambiguous hostnames, fragments, or unsupported ports. 6. Resolve and block loopback, link-local, private, multicast, and cloud metadata destinations unless a narrowly scoped local-development exception applies. 7. Apply equivalent validation to every redirect target. Prefer disabling redirects for authenticated POST requests. 8. Never forward `X-API-Key` or `Payment-Proof` headers when the request origin changes. 9. Consider requiring credentials to be passed explicitly for a selected trusted endpoint rather than automatically attaching ambient environment credentials to every custom endpoint. 10. Add tests proving that HTTP, metadata addresses, private-network destinations, and cross-origin redirects are rejected. ]]>
