fix(privacy): zero third-party requests from browser (v0.2.2)

- Remove Google Fonts links from web dashboard and testpage: opening
  the page no longer sends requests (IP/UA) to Google; system font
  stack renders identically, works offline and loads faster in CN
- Override default python-httpx User-Agent with a browser UA on all
  Xiaomi requests (matches cookie-based login origin, removes script
  fingerprint)
- PRIVACY.md: document zero-CDN frontend and minimal outbound headers
This commit is contained in:
binglua committed 2026-09-03 22:47:34 +08:00
1 parent a47a8470f8
commit 45f1d2e701
7 files changed
+24 -10

No files matched your search

+6
View File
@@ -1,5 +1,11 @@
# Changelog # Changelog
## 0.2.2(零第三方请求)
- 移除 Web 仪表盘与测试页的 Google Fonts 外链:打开页面不再向 Google 发送任何请求(此前浏览器会上传 IP/UA),改用系统字体栈,国内加载也更快、离线可渲染
- 发往小米的请求覆盖默认 `python-httpx/*` User-Agent 为浏览器 UA,去除脚本指纹(与 Cookie 登录来源一致)
- `docs/PRIVACY.md` 补充浏览器端零外链与最小化出站请求头说明
## 0.2.1(隐私加固) ## 0.2.1(隐私加固)
- 数据安全审计文档 `docs/PRIVACY.md`:全部对外请求清单(仅小米域名)、本机数据存放表、威胁模型与自验方法 - 数据安全审计文档 `docs/PRIVACY.md`:全部对外请求清单(仅小米域名)、本机数据存放表、威胁模型与自验方法
+5 -1
View File
@@ -39,7 +39,11 @@
扫码登录流程中由**小米动态下发**的跳转地址(`c3.account.xiaomi.com`、`c3.lp.account.xiaomi.com` 等)也全部位于 `*.xiaomi.com` 小米域名下。 扫码登录流程中由**小米动态下发**的跳转地址(`c3.account.xiaomi.com`、`c3.lp.account.xiaomi.com` 等)也全部位于 `*.xiaomi.com` 小米域名下。
**不存在**:遥测(telemetry)、统计(analytics)、Sentry/PostHog/Mixpanel 等上报 SDK、GitHub star 上报、版本检查回传、任何第三方域名。可用以下命令自行复核: **不存在**:遥测(telemetry)、统计(analytics)、Sentry/PostHog/Mixpanel 等上报 SDK、GitHub star 上报、版本检查回传、任何第三方域名。
**浏览器端同样零外链**:Web 仪表盘与测试页不引用任何 CDN(无 Google Fonts/图表库外链),字体全部使用系统字体栈——打开页面不会向任何第三方发出请求,离线也能完整渲染。
**最小化出站请求头**:发往小米的请求不携带脚本指纹(覆盖默认 `python-httpx/*` User-Agent 为浏览器 UA,与 Cookie 登录来源一致),请求体只含协议必需字段。可用以下命令自行复核:
```bash ```bash
grep -rn "https\?://" src/ --include="*.py" | grep -v 127.0.0.1 # 应只见 *.xiaomi.com / *.io.mi.com grep -rn "https\?://" src/ --include="*.py" | grep -v 127.0.0.1 # 应只见 *.xiaomi.com / *.io.mi.com
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project] [project]
name = "mi-fitness-mcp" name = "mi-fitness-mcp"
version = "0.2.1" version = "0.2.2"
description = "MCP server for Mi Fitness data access" description = "MCP server for Mi Fitness data access"
readme = "README.md" readme = "README.md"
license = {text = "MIT"} license = {text = "MIT"}
@@ -130,7 +130,17 @@ class MiFitnessCloudAdapter(DataAdapter):
self._connected = False self._connected = False
return False return False
await self._close_client() await self._close_client()
self._client = httpx.AsyncClient(timeout=self.http_timeout, follow_redirects=False) self._client = httpx.AsyncClient(
timeout=self.http_timeout,
follow_redirects=False,
# 浏览器 UA 与 Cookie 登录来源一致,避免暴露 python-httpx 指纹
headers={
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
)
},
)
try: try:
await self._login_with_token(self.user_id, self.pass_token) await self._login_with_token(self.user_id, self.pass_token)
# Trust an explicitly configured region. Expensive cross-region discovery # Trust an explicitly configured region. Expensive cross-region discovery
+1 -1
View File
@@ -184,7 +184,7 @@ async def _gate(x_api_key: str | None = Header(default=None)) -> None:
app = FastAPI( app = FastAPI(
title="Mi Fitness API", title="Mi Fitness API",
version="0.2.1", version="0.2.2",
description="小米运动健康数据 REST API(多 Key 鉴权 + 扫码登录 + 本地 SQLite 缓存)", description="小米运动健康数据 REST API(多 Key 鉴权 + 扫码登录 + 本地 SQLite 缓存)",
lifespan=lifespan, lifespan=lifespan,
dependencies=[Depends(_gate)], dependencies=[Depends(_gate)],
@@ -5,9 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mi Fitness MCP | 健康数据中心与调试控制台</title> <title>Mi Fitness MCP | 健康数据中心与调试控制台</title>
<link rel="stylesheet" href="/static/css/style.css"> <link rel="stylesheet" href="/static/css/style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
</head> </head>
<body> <body>
<div id="app-container"> <div id="app-container">
-3
View File
@@ -5,9 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mi Fitness MCP | 健康数据中心与调试控制台</title> <title>Mi Fitness MCP | 健康数据中心与调试控制台</title>
<link rel="stylesheet" href="/static/css/style.css"> <link rel="stylesheet" href="/static/css/style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
</head> </head>
<body> <body>
<div id="app-container"> <div id="app-container">