T09 · Insecure Skill Coding Practices
- Location
- src/index.ts:15
- Finding
- API token can be transmitted over plaintext HTTP## Vulnerability Details **File Location**: `src/index.ts:15-17`, `src/index.ts:247-260`, and `src/index.ts:298-302` **Vulnerability Type**: Plaintext transmission of sensitive credentials **Risk Level**: High ### Vulnerable Code ```ts const BACKUP_URL1 = process.env.STOCKTODAY_BACKUP_URL1 || "http://111.229.164.2:8083/"; const BACKUP_URL2 = process.env.STOCKTODAY_BACKUP_URL2 || "http://124.223.112.152:6331/"; const BACKUP_URL3 = process.env.STOCKTODAY_BACKUP_URL3 || "http://110.42.211.9:9900/"; ``` ```ts async function fetchOne(url: string, endpoint: string, formData: URLSearchParams): Promise<{status: number; data: any; raw: string}> { try { const res = await fetch(`${url}${endpoint}`, { method: "POST", body: formData, headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Client-Type": "StockToday-skill", "X-Client-Version": "1.3.11" }, signal: AbortSignal.timeout(30000) }); const raw = await res.text(); let data: any; try { data = JSON.parse(raw); } catch { data = raw; } return { status: res.status, data, raw }; } catch (e: any) { return { status: 0, data: null, raw: e?.message || String(e) }; } } ``` ```ts const formData = new URLSearchParams(); formData.append("TOKEN", token); const urls = [BASE_URL, BACKUP_URL1, BACKUP_URL2, BACKUP_URL3]; ``` ### Technical Analysis The API credential is included in a URL-encoded POST body for every backend request. The Skill defines three default fallback gateways using unencrypted HTTP and does not enforce an HTTPS-only policy for either the primary URL or fallback URLs. Any request sent to an HTTP endpoint exposes the token and response data to network observers and active intermediaries. Encryption is especially important here because possession of the token is sufficient to authenticate API requests. The current fallback loop ...[truncated 1532 chars]
- Remediation
- ## Remediation Suggestions 1. Remove all default plaintext HTTP fallback gateways. 2. Require every configured backend URL to use the `https:` protocol: ```ts function requireHttps(raw: string): string { const parsed = new URL(raw); if (parsed.protocol !== "https:") { throw new Error("StockToday backend URLs must use HTTPS"); } return parsed.toString(); } ``` 3. Apply this validation to `STOCKTODAY_URL` and every configured fallback URL before processing requests. 4. Replace bare IP addresses with authenticated HTTPS domain names whose certificates can be validated. 5. Do not provide an option to disable TLS certificate validation. 6. Correct the fallback loop separately so that only genuine transport failures or retryable responses cause failover, while preserving the HTTPS-only requirement. 7. Rotate any token that may previously have been sent to an HTTP endpoint. 8. Document the exact backend domains that receive tokens and allow administrators to enforce an outbound network allowlist.
