T09 · Insecure Skill Coding Practices
- Location
hawk/extractor.py:119- Finding
Cross-provider API credential disclosure
- Content
View full analysis
list[ExtractedMemory]: """使用配置的 LLM 从对话中提取记忆""" api_key = api_key or os.environ.get("OPENAI_API_KEY") or os.environ.get("GROQ_API_KEY") or os.environ.get("MINIMAX_API_KEY") or "" ``` ```python # hawk/extractor.py:230-238 req = urllib.request.Request( "https://api.groq.com/openai/v1/chat/completions", data=data, headers={ "Authorization": f"Bearer {api_key or 'free'}", "Content-Type": "application/json", } ) with urllib.request.urlopen(req, timeout=30) as resp: ``` ```python # hawk/wrapper.py:73-81 api_key = api_key or os.environ.get("MINIMAX_API_KEY") or os.environ.get("OPENAI_API_KEY") or "" provider = provider or os.environ.get("LLM_PROVIDER", "keyword") model = model or os.environ.get("OPENAI_MODEL", "llama-3.3-70b-versatile") if base_url is None: if provider == "minimax": base_url = os.environ.get("MINIMAX_BASE_URL", "https://api.minimaxi.com/anthropic") elif provider == "openai": base_url = "https://api.openai.com/v1" ``` ### Technical Analysis Credential selection is not scoped to the selected provider. The extractor searches OpenAI, Groq, and MiniMax environment variables in a fixed order and uses the first available value. The wrapper similarly prefers a MiniMax key even when another provider is selected. The selected value is subsequently placed in a bearer authorization header or supplied to the provider SDK. Consequently, an OpenAI key can be sent to Groq, or a MiniMax key can be sent to OpenAI. This violates credential isolation and least-privilege principles. ### Attack Path 1. ...[truncated 823 chars]- Remediation
View remediation
