T09 · Insecure Skill Coding Practices
- Location
scripts/eval.py:874- Finding
API Credential Disclosure Through Provider and Endpoint Mismatch
- Content
View full analysis
Vulnerability Details
File Location:
scripts/eval.py, lines 874-896
Vulnerability Type: API credential disclosure and insufficient endpoint validation
Risk Level: HighVulnerable Code
python def llm_judge(result: dict) -> dict | None: api_key = os.environ.get('OPENAI_API_KEY') or os.environ.get('DEEPSEEK_API_KEY', '') if not api_key: return None base = os.environ.get('OPENAI_API_BASE', 'https://api.deepseek.com') dim_lines = '\n'.join(f' {k}: {v}' for k, v in {**result['dimension_scores'], **result['expanded_scores']}.items()) ev_lines = '\n'.join(f' {e["metric"]}: {e["value"]}' for e in result['evidence'][:8]) risk_lines = '\n'.join(f' - {r}' for r in result['risk_flags']) or ' 无' prompt = LLM_JUDGE_PROMPT.format( dim_summary=dim_lines, evidence_summary=ev_lines, risk_summary=risk_lines) payload = json.dumps({ 'model': 'deepseek-chat', 'messages': [{'role': 'user', 'content': prompt}], 'temperature': 0.3, 'max_tokens': 200, }).encode() req = urllib.request.Request( f'{base}/v1/chat/completions', data=payload, headers={'Content-Type': 'application/json', 'Authorization': f'Bearer {api_key}'}, ) try: with urllib.request.urlopen(req, timeout=15) as resp: body = json.loads(resp.read())Technical Analysis
Credential selection and endpoint selection are not bound to the same provider. The code prefers
OPENAI_API_KEY, but the default endpoint ishttps://api.deepseek.com. Consequently, when an OpenAI key is present andOPENAI_API_BASEis absent, that OpenAI credential is transmitted to DeepSeek in the HTTPAuthorizationheader.In addition,
OPENAI_API_BASEis accepted without host validation. Any process or execution environment able to influence this variable can redirect the request to an arbitrar ...[truncated 1610 chars]- Remediation
View remediation
Remediation Suggestions
- Require explicit provider selection, such as
--provider openaior--provider deepseek. - Bind each provider to its corresponding key and default endpoint:
- OpenAI:
OPENAI_API_KEYand the official OpenAI API endpoint. - DeepSeek:
DEEPSEEK_API_KEYand the official DeepSeek API endpoint.
- OpenAI:
- Do not fall back from one provider's credential to another provider's endpoint.
- Validate the parsed URL before constructing the request:
- Require HTTPS.
- Require an approved hostname.
- Reject embedded credentials, unexpected ports, fragments, and non-HTTP schemes.
- If custom endpoints are necessary, require a dedicated opt-in flag and a provider-specific base variable.
- Display the destination hostname and categories of data being transmitted before the optional request.
- Minimize transmitted evidence and redact values that may contain workspace-specific or operationally sensitive information.
- Add automated tests proving that an OpenAI key cannot be sent to DeepSeek and that unapproved hosts are rejected.
- Require explicit provider selection, such as
