T05 · Unauthorized Access and Privilege Escalation
- Location
backend/app/api/routes.py:139- Finding
Unauthenticated API Endpoint Discloses Decrypted Provider API Keys
- Content
View full analysis
Vulnerability Details
File Location:
backend/app/api/routes.py:139-155; supporting credential decryption inbackend/secure_config.py:78-96and permissive CORS inbackend/app/main.py:23-29
Vulnerability Type: Missing authentication and sensitive-data exposure
Risk Level: CriticalVulnerable Code
python @router.get("/provider/{provider_id}") async def get_provider_config(provider_id: str): """Get a single provider configuration from encrypted storage.""" try: config = secure_config.get_provider(provider_id) if config is None: return { "providerId": provider_id, "baseUrl": "", "apiKey": "", "contextWindow": 64000, "maxTokens": 8000, } return {"providerId": provider_id, **config} except Exception as e: raise HTTPException(status_code=500, detail=str(e))The returned configuration is decrypted by the following code:
python def get_provider(self, provider_id: str) -> Optional[Dict]: try: if provider_id not in self.config.get("providers", {}): return None provider = self.config["providers"][provider_id] decrypted_apikey = SecureConfig._cipher.decrypt( provider["apiKey"].encode() ).decode() return { "baseUrl": provider["baseUrl"], "apiKey": decrypted_apikey, "contextWindow": provider.get("contextWindow", 64000), "maxTokens": provider.get("maxTokens", 8000), } except Exception as e: print(f"[SecureConfig] Failed to get provider configuration: {e}") return NoneThe application also enables unrestricted cross-origin requests:
python app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )Technical Analysis
The provider endpoint has no authent ...[truncated 1892 chars]
- Remediation
View remediation
Remediation Suggestions
- Remove
apiKeyfrom all provider read responses. - Return only masked metadata, such as
hasApiKey: trueor a suffix like****abcd. - Require re-entry of a key when the user wants to replace it.
- Add authentication to every API endpoint, using a high-entropy token generated at startup or an authenticated local session.
- Replace wildcard CORS with the exact trusted WebUI origin:
python allow_origins=["http://127.0.0.1:9131"] - Validate the
OriginandHostheaders and reject untrusted origins. - Add CSRF protection for all state-changing endpoints.
- Keep the service bound exclusively to loopback and document that it must not be exposed through a proxy.
- Rotate all API keys that may have been exposed through this endpoint.
- Remove
