T09 · Insecure Skill Coding Practices
- Location
SKILL.md:136- Finding
Exposed Billing API Credential and Unnecessary Transmission of User Identifiers
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 136–185
Vulnerability Type: Hardcoded secret and sensitive-data exposure to a third-party billing service
Risk Level: HighVulnerable Code
javascript const BILLING_API_URL = 'https://skillpay.me'; const BILLING_API_KEY = 'sk_b82c6ede30fbac400f2ccbaefc57a013270ab0af29e7cd06746511a51977a5aa'; const SKILL_ID = 'f6a281ea-7575-40f0-a6c3-25068de08bce'; // ① Check balance / 查余额 async function checkBalance(userId) { const resp = await fetch( `${BILLING_API_URL}/api/v1/billing/balance?user_id=${userId}`, { headers: { 'X-API-Key': BILLING_API_KEY } } ); const data = await resp.json(); return data.balance; // USDT amount } // ② Charge per call / 每次调用扣费 async function chargeUser(userId) { const resp = await fetch(`${BILLING_API_URL}/api/v1/billing/charge`, { method: 'POST', headers: { 'X-API-Key': BILLING_API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ user_id: userId, skill_id: SKILL_ID, amount: 0.001, // USDT per call }), }); const data = await resp.json(); if (data.success) { return { ok: true, balance: data.balance }; } // Insufficient balance → get payment link return { ok: false, balance: data.balance, paymentUrl: data.payment_url }; } // ③ Generate payment link / 生成充值链接 async function getPaymentLink(userId, amount) { const resp = await fetch(`${BILLING_API_URL}/api/v1/billing/payment-link`, { method: 'POST', headers: { 'X-API-Key': BILLING_API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ user_id: userId, amount }), }); const data = await resp.json(); return data.payment_url; // BNB Chain USDT payment link }Technical Analysis
The Skill embeds a live-looking billing API key directly in publicly readable S ...[truncated 2798 chars]
- Remediation
View remediation
Remediation Suggestions
- Revoke and rotate the exposed API key immediately. Treat it as compromised even if no abuse has yet been observed.
- Remove all credentials from
SKILL.md, examples, repositories, generated packages, and client-accessible code. - Move billing operations to a trusted backend. The Skill should call a narrowly scoped backend operation without receiving the billing provider's master or shared API credential.
- Store backend credentials in a managed secret store or protected runtime environment variable and prevent them from appearing in logs or error messages.
- Issue separate, short-lived, narrowly scoped credentials per deployment or operation. Avoid one static credential shared by all installations.
- Enforce server-side authorization for every user and Skill combination. Possession of the API key alone must not permit access to arbitrary user accounts.
- Require explicit user confirmation immediately before each charge, including the amount, currency, chain, recipient, and reason.
- Add replay protection, idempotency keys, rate limits, anomaly detection, audit logging, and per-user charging limits.
- Do not place user identifiers in URL query strings. Use an authenticated request body where possible and configure all infrastructure to redact identifiers and authorization headers.
- Prefer opaque, service-specific pseudonymous identifiers instead of stable platform or wallet-linked user identifiers.
- Document what data is transmitted to the billing provider, why it is required, and how long it is retained. Obtain appropriate consent before disclosure.
- Review billing-provider logs and account history for prior misuse of the exposed key.
