T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/client.js:7
- Finding
- Bearer Credential Disclosure Through Unvalidated Proxy URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/client.js:7-18`, `scripts/client.js:35-41`, `scripts/sora2.js:53-59`, and `scripts/sora2.js:65-73` **Vulnerability Type**: Server-Side Request Forgery-like credential exfiltration through an unvalidated destination **Risk Level**: High ### Vulnerable Code `scripts/client.js:7-18` loads proxy URLs from an environment-controlled JSON value without validating their schemes or origins: ```js const raw = process.env.AIZNT_PROXY_URLS; if (!raw || !String(raw).trim()) { throw new Error('缺少 AIZNT_PROXY_URLS(JSON 字符串,与 GET /miniapp/ai/chat/credentials 返回的 aiznt_proxy_urls 一致)'); } let urls; try { urls = typeof raw === 'string' ? JSON.parse(raw) : raw; } catch { throw new Error('AIZNT_PROXY_URLS 不是合法 JSON'); } if (!urls || typeof urls !== 'object') { throw new Error('AIZNT_PROXY_URLS 必须是对象'); } ``` `scripts/client.js:35-41` places the sensitive token in the `Authorization` request header and sends the request to the supplied URL: ```js function authHeaders(token, extra = {}) { return { Authorization: `Bearer ${token}`, ...extra, }; } async function fetchJson(url, options = {}) { const res = await fetch(url, options); ``` `scripts/sora2.js:53-59` sends both the Bearer token and user-supplied video-generation request body to the configured submission URL: ```js const url = urls.v2_videos_generations; if (!url) throw new Error('AIZNT_PROXY_URLS 缺少 v2_videos_generations'); const body = bodyFromOpts(); const data = await fetchJson(url, { method: 'POST', headers: authHeaders(token, { 'Content-Type': 'application/json' }), body: JSON.stringify(body), }); ``` `scripts/sora2.js:65-73` sends the Bearer token to the configured task-status URL: ```js const taskId = opts['task-id']; if (!taskId) throw new Error('需要 --task-id'); const tpl = urls.v2_videos_generations_fetch; if (!tpl) throw new Error('AIZNT_PROXY_ ...[truncated 3293 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Enforce HTTPS** - Parse every configured endpoint with `new URL(value)`. - Reject any protocol other than `https:`. - Reject URLs containing embedded usernames or passwords. 2. **Allowlist trusted destinations** - Maintain an explicit list of approved proxy hostnames and ports in code or trusted immutable configuration. - Compare normalized URL origins rather than using substring or suffix-only checks. - Avoid accepting arbitrary hosts merely because they share part of a trusted domain name. 3. **Validate each configured endpoint before use** - Validate `v2_videos_generations` and `v2_videos_generations_fetch` immediately after parsing `AIZNT_PROXY_URLS`. - Reject loopback, link-local, private-network, metadata-service, and other non-approved destinations unless a specifically approved deployment requires them. - Reject malformed URL templates and permit placeholders only in expected path components. 4. **Constrain redirects** - Prefer `redirect: 'manual'` for credential-bearing requests. - If redirects are required, inspect each redirect target and resend credentials only when the target remains on an explicitly approved origin. - Set a conservative redirect limit. 5. **Reduce credential scope** - Use short-lived, revocable, service-scoped tokens limited to the required video submission and status operations. - Avoid using a general conversation or account token if a narrower proxy-specific credential is available. 6. **Protect configuration integrity** - Accept proxy URLs only from a trusted credential service or administrator-controlled configuration. - Prevent untrusted users and unrelated Skills from modifying `AIZNT_PROXY_URLS`. - Log configuration changes without logging the token itself. 7. **Add automated tests** - Verify rejection of HTTP URLs, attacker-controlled hosts, embedded credentials, unexpected ports, malformed templates, and disallowed network r ...[truncated 103 chars]
