T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/token.js:16
- Finding
- Configurable API Endpoint Can Redirect CJ Credentials to an Untrusted Server## Vulnerability Details **File Location**: `scripts/token.js:16-17, 25` and `scripts/source.js:35-41` **Vulnerability Type**: Unrestricted credential destination **Risk Level**: High ### Vulnerable Code `scripts/token.js:16-17, 25`: ```js async function refreshToken(apiKey, baseUrl){ const url = `${baseUrl.replace(/\/$/,'')}/authentication/getAccessToken`; const r = await axios.post(url, { apiKey }, { headers: { 'Content-Type':'application/json' }, timeout: 60000 }); if(!r.data?.result) throw new Error(`Token refresh failed: ${JSON.stringify(r.data).slice(0,300)}`); return r.data.data.accessToken; } const baseUrl = cfg.baseUrl || 'https://developers.cjdropshipping.com/api2.0/v1'; ``` `scripts/source.js:35-41`: ```js const baseUrl = (cfg.baseUrl || 'https://developers.cjdropshipping.com/api2.0/v1').replace(/\/$/,''); const token = cfg.accessToken; if(!token) throw new Error('Missing accessToken in cj-api.json (run token.js)'); const url = `${baseUrl}/product/listV2`; const res = await axios.get(url, { headers: { 'CJ-Access-Token': token }, ``` ### Technical Analysis Both scripts obtain `baseUrl` directly from `cj-api.json` without validating its scheme or hostname. The token helper sends the long-lived CJ API key in a POST body to the configured endpoint, while the sourcing script sends the CJ access token in an HTTP header to that endpoint. The Skill is explicitly dedicated to the CJ Dropshipping API, so sending credentials to arbitrary configurable origins is not necessary for its declared functionality. No exact-host allowlist, HTTPS requirement, redirect restriction, or destination confirmation protects these credentials. Axios may also follow HTTP redirects under its default behavior. Consequently, validating only the initial URL would be insufficient unless credential-bearing redirects are also prohibited or carefully constrained. ### Attack Path 1. An attacker or less-trusted ...[truncated 1342 chars]
- Remediation
- ## Remediation Suggestions 1. Remove user-configurable origins if only the official CJ service is supported: ```js const baseUrl = 'https://developers.cjdropshipping.com/api2.0/v1'; ``` 2. If endpoint configuration is required for legitimate testing, parse it with `URL` and enforce: - `https:` as the protocol; - an exact hostname allowlist; - an approved port; - an approved base path; - no embedded username or password. 3. Reject IP literals, lookalike domains, and hostname suffix checks such as `endsWith("cjdropshipping.com")`, which can be bypassed by attacker-controlled subdomains. 4. Disable redirects for requests carrying credentials, or independently validate every redirect destination before forwarding credentials. 5. Keep test or mock endpoint support behind an explicit development-only option that cannot be enabled through the production credential file. 6. Document that credential-bearing requests are sent only to the official CJ origin.
