T09 · Insecure Skill Coding Practices
Error
- Location
- main.py:10
- Finding
- Hardcoded SkillPay API Credential Can Be Transmitted to a Configurable Network Endpoint## Vulnerability Details **File Location**: `main.py:10-11`, with credential transmission sinks at `main.py:203-218` and `main.py:230-235` **Vulnerability Type**: Hardcoded secret and unsafe credential destination configuration **Risk Level**: High ### Vulnerable Code ```python SKILLPAY_API_KEY = os.getenv("SKILLPAY_API_KEY", "sk_8b36c2ca9e774eb0243752f907b086e78c8af866a4088d3e3475113ed446b71") SKILLPAY_API_BASE = os.getenv("SKILLPAY_API_BASE", "https://api.skillpay.me") ``` The embedded credential is transmitted through the following functions: ```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) ``` ```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) ``` ### Technical Analysis The application contains a live-looking SkillPay bearer credential as the default value of `SKILLPAY_API_KEY`. This contradicts the configuration in `skill.yaml`, which declares that environment variable as required. Anyone with access to the source package can recover and attempt to reuse the credential. The credential is included in the `Authorization` header of requests ...[truncated 2343 chars]
- Remediation
- ## Remediation Suggestions 1. Revoke and rotate the exposed SkillPay credential immediately; source removal alone cannot invalidate copies already distributed. 2. Remove the hardcoded fallback and require secret injection: ```python SKILLPAY_API_KEY = os.getenv("SKILLPAY_API_KEY") if not SKILLPAY_API_KEY: raise RuntimeError("SKILLPAY_API_KEY is required") ``` 3. Store the credential in a managed secret service or deployment secret facility rather than source control, images, or ordinary configuration files. 4. Pin or allowlist the billing API origin. If custom endpoints are required for testing, permit them only in an explicit non-production mode. 5. Require HTTPS and validate the parsed scheme and hostname before attaching the authorization header. 6. Use a narrowly scoped provider credential that can perform only the charge operations required by this skill. 7. Add automated secret scanning to commits and release artifacts. 8. Avoid logging authorization headers, environment dumps, or complete outbound request objects. 9. Establish periodic key rotation and monitoring for abnormal charge activity.
