T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/feishu_api.py:13
- Finding
- Configurable Service Endpoints Can Expose Credentials and Private Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/feishu_api.py:13-24`; equivalent endpoint handling also appears in `scripts/asr.py:11-30`, `scripts/senseaudio_asr.py:11-30`, `scripts/tts.py:11-50`, and `scripts/senseaudio_tts.py:11-52` **Vulnerability Type**: Unvalidated security-sensitive service endpoints **Risk Level**: Medium ### Vulnerable Code ```python class FeishuClient: def __init__(self) -> None: self.base_url = get_optional('FEISHU_BASE_URL', 'https://open.feishu.cn').rstrip('/') self.app_id = get_required('FEISHU_APP_ID') self.app_secret = get_required('FEISHU_APP_SECRET') def tenant_access_token(self) -> str: resp = requests.post( f'{self.base_url}/open-apis/auth/v3/tenant_access_token/internal', headers={'Content-Type': 'application/json; charset=utf-8'}, json={'app_id': self.app_id, 'app_secret': self.app_secret}, timeout=30, ) ``` The SenseAudio clients follow the same pattern: ```python class SenseAudioASR: def __init__(self) -> None: base_url = get_optional('SENSEAUDIO_BASE_URL', 'https://api.senseaudio.cn').rstrip('/') self.api_url = f'{base_url}/v1/audio/transcriptions' self.api_key = get_required('SENSEAUDIO_API_KEY') self.model = get_optional('SENSEAUDIO_ASR_MODEL', 'sense-asr') def transcribe(self, audio_path: str | Path, language: str | None = 'zh') -> dict[str, Any]: path = Path(audio_path) with path.open('rb') as f: files = {'file': (path.name, f)} data: dict[str, Any] = {'model': self.model, 'response_format': 'json'} if language and self.model != 'sense-asr-deepthink': data['language'] = language resp = requests.post( self.api_url, headers={'Authorization': f'Bearer {self.api_key}'}, data=data, files=files, timeout=120, ...[truncated 2251 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse configured endpoints with a strict URL parser before issuing requests. 2. Require the `https` scheme and reject plaintext HTTP. 3. Allow only `open.feishu.cn` for Feishu and `api.senseaudio.cn` for SenseAudio by default. 4. If self-hosted endpoints are required, place them behind a separate explicit opt-in setting and document that credentials and user content will be sent there. 5. Reject URLs containing embedded credentials, fragments, unexpected ports, or malformed hostnames. 6. Disable redirects or validate every redirect destination before forwarding requests containing credentials or private content. 7. Protect `.env` files with restrictive filesystem permissions and ensure they are excluded from source control. 8. Avoid including complete provider responses in exceptions where they could contain credentials, tokens, or sensitive metadata. ]]>
