T09 · Insecure Skill Coding Practices
Error
- Location
- src/config.js:4
- Finding
- Operator bearer token can be transmitted to an arbitrary or plaintext endpoint<![CDATA[ ## Vulnerability Details **File Location**: `src/config.js:4-29`, `src/connect.js:9-25` **Vulnerability Type**: Arbitrary credential destination and plaintext transmission **Risk Level**: High ### Vulnerable Code From `src/config.js`: ```js export function loadConfig(env = process.env) { const baseUrl = trimTrailingSlash(env.FTTRAI_RPC_URL || DEFAULT_FTTRAI_RPC_URL); const token = env.FTTRAI_OPERATOR_AUTH_TOKEN || ""; const timeoutMs = parsePositiveInt(env.FTTRAI_TIMEOUT_MS, 30000); const maxRetries = parsePositiveInt(env.FTTRAI_MAX_RETRIES, 2); const missing = []; if (!token) missing.push("FTTRAI_OPERATOR_AUTH_TOKEN"); if (missing.length > 0) { const err = new Error(`缺少必要环境变量: ${missing.join(", ")}`); err.code = "missing_config"; throw err; } let parsedUrl; try { parsedUrl = new URL(baseUrl); } catch { const err = new Error("FTTRAI_RPC_URL 不是有效 URL"); err.code = "invalid_config"; throw err; } if (!["http:", "https:"].includes(parsedUrl.protocol)) { const err = new Error("FTTRAI_RPC_URL 只支持 http 或 https"); err.code = "invalid_config"; throw err; } ``` From `src/connect.js`: ```js async unary(procedure, body = {}) { const url = `${this.config.baseUrl}${procedure}`; let lastError; for (let attempt = 0; attempt <= this.config.maxRetries; attempt += 1) { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs); try { const response = await fetch(url, { method: "POST", headers: { "Authorization": `Bearer ${this.config.token}`, "Content-Type": "application/json", "Accept": "application/json", }, body: JSON.stringify(body), signal: controller.signal, }); ``` ### Technical Analysis The configurable `FTTRAI_RPC_URL` is validated only as an HTTP or HTTPS URL. No check requires TLS, restrict ...[truncated 2497 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require HTTPS for normal operation: ```js if (parsedUrl.protocol !== "https:") { const err = new Error("FTTRAI_RPC_URL must use HTTPS"); err.code = "invalid_config"; throw err; } ``` 2. Allowlist the documented production hostname, such as `fms-main.fttrai.com`, unless a clearly labeled development mode is enabled. 3. Do not permit production operator credentials to be used with custom endpoints. Use separate, restricted development credentials for test or private deployments. 4. Reject unexpected URL components, including embedded usernames or passwords, fragments, and unauthorized ports. 5. Consider constructing RPC URLs with `new URL(procedure, baseUrl)` and validate the final URL immediately before transmission. 6. Configure an explicit redirect policy, such as `redirect: "error"`, or validate every redirect destination before forwarding credentials. 7. Add automated tests confirming rejection of: - Plaintext HTTP endpoints. - Untrusted hosts. - Embedded URL credentials. - Unexpected ports. - Redirects to different origins. 8. Rotate the operator token if it may previously have been used with an untrusted or plaintext endpoint. ]]>
