- Location
- bridge/investorclaw_bridge/serve.py:120
- Finding
- Unauthenticated sensitive management interfaces lack CSRF and remote-access safeguards<![CDATA[
## Vulnerability Details
**File Location**: `bridge/investorclaw_bridge/serve.py:120-121, 240-269`; `bridge/investorclaw_bridge/dashboard.py:1522-1619`; `bridge/investorclaw_bridge/mcp/transport.py:239-254`
**Vulnerability Type**: Missing authentication, missing CSRF protection, and disabled DNS-rebinding protection
**Risk Level**: High
### Vulnerable Code
```python
mcp_bind = os.environ.get("IC_MCP_BIND", "0.0.0.0:8090")
dashboard_bind = os.environ.get("IC_DASHBOARD_BIND", "0.0.0.0:8092")
```
```python
_allowed_hosts = os.environ.get("MCP_ALLOWED_HOSTS", "").strip()
if _allowed_hosts:
_sec = TransportSecuritySettings(
enable_dns_rebinding_protection=True,
allowed_hosts=[h.strip() for h in _allowed_hosts.split(",") if h.strip()],
)
else:
_sec = TransportSecuritySettings(enable_dns_rebinding_protection=False)
mcp_app = FastMCP("investorclaw", transport_security=_sec)
```
```python
@app.post("/dashboard/settings/keys", include_in_schema=False)
async def settings_save_key(request: Request) -> RedirectResponse:
form = await request.form()
name = (form.get("key_name") or "").strip()
value = (form.get("key_value") or "").strip()
if not name or not value:
return RedirectResponse(
url="/dashboard/settings?message=Missing+name+or+value",
status_code=303,
)
import inspect as _inspect
result = set_key(name, value)
if _inspect.iscoroutine(result):
result = await result
```
```python
@app.post("/dashboard/upload", include_in_schema=False)
async def upload_portfolio(request: Request) -> RedirectResponse:
"""Multipart upload — write to /data/portfolios/, then trigger setup."""
from urllib.parse import quote
try:
form = await request.form()
except Exception as e:
return RedirectResponse(
url=f"/dashboard/settings?message={quote('Upload parse failed: ' + str(e))}",
status_code=303,
)
```
```python
...[truncated 2964 chars]
- Remediation
- <![CDATA[
## Remediation Suggestions
1. Require authentication for every endpoint except narrowly scoped health and version checks.
2. Support a mandatory bearer token or authenticated session for MCP, REST, setup, dashboard, upload, key-management, regeneration, and response-management routes.
3. Add CSRF tokens to all browser forms and validate `Origin` and `Referer` headers for state-changing requests.
4. Use `SameSite=Strict`, `HttpOnly`, and `Secure` attributes if cookie-based sessions are introduced.
5. Keep MCP DNS-rebinding protection enabled and provide an explicit allowlist for `localhost`, loopback addresses, and approved Compose service names.
6. Refuse startup on a non-loopback bind address unless authentication is configured.
7. Add rate limits and concurrency limits to refresh, initialization, upload, and regeneration operations.
8. Document reverse-proxy requirements, including TLS and authentication, for remote deployments.
9. Add integration tests proving that unauthenticated mutations, invalid CSRF tokens, unapproved Host headers, and unapproved Origins are rejected.
]]>