T09 · Insecure Skill Coding Practices
- Location
scripts/billing.py:37- Finding
Unrestricted Billing Endpoint Can Expose the SkillPay API Credential
- Content
View full analysis
None: self.api_key = api_key self.base_url = (base_url or os.getenv("SKILLPAY_BASE_URL") or "https://skillpay.me").rstrip("/") self.charge_url = charge_url or os.getenv("SKILLPAY_CHARGE_URL") if not self.charge_url: charge_path = os.getenv("SKILLPAY_CHARGE_PATH", "/charges") self.charge_url = f"{self.base_url}{charge_path}" self.session = requests.Session() def charge(self, call_name: str, amount_usdt: str, user_ref: str, idempotency_key: str) -> BillingResult: payload = { "call_name": call_name, "amount": amount_usdt, "currency": "USDT", "user_ref": user_ref, "idempotency_key": idempotency_key, "timestamp": int(time.time()), } headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", "Idempotency-Key": idempotency_key, } delay = 0.8 for attempt in range(3): try: resp = self.session.post(self.charge_url, json=payload, headers=headers, timeout=12) ``` ### Technical Analysis The billing destination is taken directly from `SKILLPAY_CHARGE_URL` or assembled from `SKILLPAY_BASE_URL` and `SKILLPAY_CHARGE_PATH`. The resulting URL is not validated before the SkillPay API key is placed in the `Authorization` header and transmitted. There is no enforcement of: - HTTPS transport. - An approved SkillPay hostname. - A safe destination port. - The absence of embedded URL credentials. - A canonical and exp ...[truncated 1921 chars]- Remediation
View remediation
