T09 · Insecure Skill Coding Practices
- Location
scripts/billing_config.py:1- Finding
Hard-Coded SkillPay API Credential Transmitted with User Data
- Content
View full analysis
Vulnerability Details
File Location:
scripts/billing_config.py:1-4,scripts/billing.py:11-17, andscripts/billing.py:29-46
Vulnerability Type: Hard-coded secret and insecure credential transmission
Risk Level: HighVulnerable Code
scripts/billing_config.py:1-4:python SKILLPAY_API_KEY = "sk_41b22ea52b5a803442973b84ec1cd8f395ed098a3890905f8a196a4ffdf43c87" SKILL_ID = "xanadu-stock-screener" OWNER_WALLET = "0xF194917738617118dfff40E0542cea20Cf7dDC55" DEFAULT_PRICE = 0.001scripts/billing.py:11-17:python # Load config try: from billing_config import SKILLPAY_API_KEY, SKILL_ID, DEFAULT_PRICE, OWNER_WALLET except ImportError: SKILLPAY_API_KEY = os.environ.get("SKILLPAY_API_KEY") SKILL_ID = "xanadu-social-manager" DEFAULT_PRICE = 0.001 OWNER_WALLET = Nonescripts/billing.py:29-46:python def charge(self, user_id: str, amount: float = None) -> Dict: """Charge user for skill usage""" amount = amount or DEFAULT_PRICE try: response = requests.post( f"{self.base_url}/charge", json={ "api_key": self.api_key, "skill_id": self.skill_id, "user_id": user_id, "amount": amount }, timeout=10 ) return response.json() except Exception as e: return {"success": False, "error": str(e)}Technical Analysis
A live-looking SkillPay API key is embedded directly in a source file distributed with the project. Anyone who can read the package can recover and attempt to reuse this credential. The billing client subsequently places that credential, a caller-supplied user identifier, the skill identifier, and the requested charge amount in the body of an outbound request to
https://api.skillpay.me/v1/charge.HTTPS protects the connection in transit when cert ...[truncated 2195 chars]
- Remediation
View remediation
Remediation Suggestions
- Immediately revoke and rotate the exposed SkillPay API key. Treat it as compromised even if the repository was not intentionally public.
- Remove the key from the current source and, where applicable, purge it from version-control history and distributed artifacts.
- Retrieve credentials from a deployment secret manager or environment variable. Do not provide a source-code fallback containing a real secret.
- Send credentials through the service's documented authorization mechanism, preferably an
Authorizationheader, rather than including them in the request body. - Configure application and proxy logging to redact authorization headers, API keys, user identifiers, and payment data.
- Apply server-side restrictions to the credential, including minimum scopes, spending limits, rate limits, short expiration, and source restrictions where supported.
- Validate charge amounts against an approved server-side price table. Do not allow an arbitrary caller-controlled amount to define billing behavior.
- Obtain explicit user consent before transmitting a user identifier and document the recipient, purpose, retention policy, and privacy implications.
- Remove
billing.pyandbilling_config.pyif billing is not required by the implemented stock-screening workflow. If billing is retained, reconcile the copied social-media identifiers and tiers with the declared stock-screener functionality. - Add automated secret scanning and pre-commit or CI controls to prevent future credential commits.
