T09 · Insecure Skill Coding Practices
Error
- Location
- main.py:10
- Finding
- Hard-Coded SkillPay Credential Can Be Exposed to a Configurable Network Destination<![CDATA[ ## Vulnerability Details **File Location**: `main.py:10-12`, `main.py:207-225`, and `main.py:232-242` **Vulnerability Type**: Hard-coded secret and unsafe credential transmission **Risk Level**: High ### Vulnerable Code ```python SKILLPAY_API_KEY = "sk_8b36c2ca9e774eb0243752f907b086e78c8af866a4088d3e3475113ed446b71" SKILLPAY_API_BASE = os.getenv("SKILLPAY_API_BASE", "https://api.skillpay.me") SKILLPAY_WEB_BASE = os.getenv("SKILLPAY_WEB_BASE", "https://pay.skillpay.me") ``` ```python def create_skillpay_charge(amount: str, currency: str) -> Tuple[str, str]: if not SKILLPAY_API_KEY: raise HTTPException(status_code=400, detail="Missing SKILLPAY_API_KEY") url = f"{SKILLPAY_API_BASE.rstrip('/')}/v1/charges" headers = { "Authorization": f"Bearer {SKILLPAY_API_KEY}", "Content-Type": "application/json", } body = { "amount": amount, "currency": currency, "title": "OpenClaw Skill Payment", "description": "Polymarket Movers x3", } r = requests.post(url, json=body, headers=headers, timeout=20) if r.status_code not in (200, 201): raise HTTPException(status_code=502, detail="SkillPay create charge failed") data = r.json() cid = str(data.get("id") or data.get("charge_id") or "") purl = data.get("payment_url") if not purl and cid: purl = f"{SKILLPAY_WEB_BASE.rstrip('/')}/checkout/{cid}" if not cid or not purl: raise HTTPException(status_code=502, detail="Invalid SkillPay response") return cid, purl ``` ```python def get_skillpay_status(charge_id: str) -> str: if not SKILLPAY_API_KEY: raise HTTPException(status_code=400, detail="Missing SKILLPAY_API_KEY") url = f"{SKILLPAY_API_BASE.rstrip('/')}/v1/charges/{charge_id}" headers = {"Authorization": f"Bearer {SKILLPAY_API_KEY}"} r = requests.get(url, headers=headers, timeout=20) if r.status_code != 200: raise HTTPException(status_code=502, detail="Sk ...[truncated 2534 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Revoke and rotate the exposed credential immediately; it must be treated as compromised. 2. Remove the credential from source code and repository history. 3. Read the key only from a protected runtime secret: ```python SKILLPAY_API_KEY = os.environ["SKILLPAY_API_KEY"] ``` 4. Store the key in a managed secret service or deployment secret, with access limited to this service. 5. Pin the production payment API to an exact HTTPS origin. If endpoint configurability is required for testing, validate the scheme and hostname against an explicit allowlist and prohibit redirects to untrusted origins. 6. Use separate, least-privileged credentials for development, testing, and production. 7. Restrict the provider credential to only the charge operations required by this Skill, if SkillPay supports scoped keys. 8. Add automated secret scanning and deployment checks that reject committed credentials and unapproved payment API origins. 9. Avoid logging authorization headers, secret values, or full provider responses. ]]>
