T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/main.py:78
- Finding
- Configurable API Endpoint Can Expose the Bearer Token and Uploaded Document<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:78-112` **Vulnerability Type**: Unrestricted sensitive-data transmission destination **Risk Level**: Medium ### Vulnerable Code ```python config.setdefault('SCNET_API_BASE', 'https://api.scnet.cn/api/llm/v1') return config def recognize_with_retry(ocr_type, file_path, config, retry_count=0): """ 带重试机制的 OCR 识别函数。 当遇到 429 (Too Many Requests) 时,自动等待后重试。 调用 Scnet OCR API 进行识别""" api_base = config['SCNET_API_BASE'] api_key = config['SCNET_API_KEY'] url = f"{api_base}/ocr/recognize" # 检查文件是否存在 if not os.path.isfile(file_path): sys.exit(f"错误: 文件不存在 - {file_path}") # 自动检测 MIME 类型 mime_type, _ = mimetypes.guess_type(file_path) if mime_type is None: mime_type = 'application/octet-stream' headers = { 'Authorization': f'Bearer {api_key}' } try: with open(file_path, 'rb') as f: files = { 'file': (os.path.basename(file_path), f, mime_type) } data = { 'ocrType': ocr_type, 'channelTag': "scnetSkills" } response = requests.post(url, headers=headers, data=data, files=files, timeout=60) ``` ### Technical Analysis The Skill reads `SCNET_API_BASE` from its configuration and uses it directly to construct the request URL. It does not parse or validate the URL, require HTTPS, or verify that the destination hostname is `api.scnet.cn`. The same request transmits two sensitive assets: 1. The Scnet API key in the `Authorization: Bearer` header. 2. The complete user-selected document in a multipart upload. Although remote transmission is necessary for the declared OCR functionality and is disclosed in `SKILL.md`, permitting an arbitrary destination is not necessary when the declared service endpoint is fixed. Any party capable of changing `config/.env` can redirect both assets to a server under its control. ### ...[truncated 1234 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Hard-code the approved service base URL if alternate endpoints are not a functional requirement. 2. If endpoint configuration must remain available: - Parse it with `urllib.parse.urlparse`. - Require the `https` scheme. - Require an exact allowlisted hostname such as `api.scnet.cn`. - Reject embedded credentials, unexpected ports, fragments, and malformed URLs. 3. Avoid sending a Scnet credential to custom endpoints. Custom providers should use separate provider-specific credentials. 4. Display the validated destination and require explicit user approval before transmitting sensitive documents when the destination differs from the default. 5. Add automated tests covering HTTP URLs, deceptive subdomains, user-info URL syntax, redirects, and malformed hostnames. 6. Consider disabling redirects or validating every redirect target so an approved endpoint cannot redirect credentials and files to an unapproved host. ]]>
