From 013381e88094bd6d69ec9a2be5756662e78651d3 Mon Sep 17 00:00:00 2001 From: JAYcodr <66018853+JAYcodr@users.noreply.github.com> Date: Fri, 22 May 2026 01:32:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(i18n):=20complete=20zh-CN=20translations=20?= =?UTF-8?q?for=20workspace,=20mascot,=20MCP=20Ser=E2=80=A6=20(#2440)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: agent:skill-master --- app/src/lib/i18n/chunks/zh-CN-3.ts | 13 +- app/src/lib/i18n/chunks/zh-CN-5.ts | 51 ++++--- docs/SECURITY_AUDIT.md | 211 +++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+), 33 deletions(-) create mode 100644 docs/SECURITY_AUDIT.md diff --git a/app/src/lib/i18n/chunks/zh-CN-3.ts b/app/src/lib/i18n/chunks/zh-CN-3.ts index 1846dbc5b..9a5827678 100644 --- a/app/src/lib/i18n/chunks/zh-CN-3.ts +++ b/app/src/lib/i18n/chunks/zh-CN-3.ts @@ -33,14 +33,13 @@ const zhCN3: TranslationMap = { 'workspace.building': '构建中...', 'workspace.buildSummaryTrees': '构建摘要树', 'workspace.viewVault': '查看存储库', - 'workspace.openingVaultTitle': 'Opening vault in Obsidian', + 'workspace.openingVaultTitle': '在 Obsidian 中打开存储库', 'workspace.openingVaultMessage': - "If Obsidian doesn't open, install it from obsidian.md or use Reveal Folder. Vault path:", - 'workspace.openVaultFailedTitle': "Couldn't open vault in Obsidian", - 'workspace.openVaultFailedMessage': - 'Use Reveal Folder to open the vault directory directly. Vault path:', - 'workspace.revealVaultFailed': "Couldn't reveal vault folder", - 'workspace.revealFolder': 'Reveal Folder', + '如果 Obsidian 没有打开,请从 obsidian.md 安装或使用"显示文件夹"。存储库路径:', + 'workspace.openVaultFailedTitle': '无法在 Obsidian 中打开存储库', + 'workspace.openVaultFailedMessage': '使用"显示文件夹"直接打开存储库目录。存储库路径:', + 'workspace.revealVaultFailed': '无法显示存储库文件夹', + 'workspace.revealFolder': '显示文件夹', 'workspace.graphLoadFailed': '无法加载记忆图谱', 'workspace.loadingGraph': '正在加载记忆图谱...', 'workspace.graphViewMode': '记忆图谱视图模式', diff --git a/app/src/lib/i18n/chunks/zh-CN-5.ts b/app/src/lib/i18n/chunks/zh-CN-5.ts index ff6312d73..8c6a4f068 100644 --- a/app/src/lib/i18n/chunks/zh-CN-5.ts +++ b/app/src/lib/i18n/chunks/zh-CN-5.ts @@ -443,39 +443,38 @@ const zhCN5: TranslationMap = { 'settings.appearance.modeSystem': '跟随系统', 'settings.appearance.modeSystemDesc': '跟随操作系统外观设置。', 'settings.appearance.helperText': - 'Dark mode switches the entire app — chat, settings, panels — to a dim palette. "Match system" follows your OS appearance and updates live.', - 'settings.mascot.characterPreview': 'Preview', - 'settings.mascot.characterStates': 'states', - 'settings.mascot.characterVisemes': 'visemes', - 'settings.mascot.colorAria': 'OpenHuman color', - 'settings.mascot.colorBlack': 'Black', - 'settings.mascot.colorBurgundy': 'Burgundy', - 'settings.mascot.colorGreen': 'Green', - 'settings.mascot.colorNavy': 'Navy', - 'settings.mascot.colorYellow': 'Yellow', - 'settings.mascot.libraryUnavailable': 'OpenHuman library unavailable', + '深色模式会将整个应用——聊天、设置、面板——切换为暗色调。"跟随系统"会同步你的操作系统外观并实时更新。', + 'settings.mascot.characterPreview': '预览', + 'settings.mascot.characterStates': '状态', + 'settings.mascot.characterVisemes': '视素', + 'settings.mascot.colorAria': 'OpenHuman 颜色', + 'settings.mascot.colorBlack': '黑色', + 'settings.mascot.colorBurgundy': '酒红色', + 'settings.mascot.colorGreen': '绿色', + 'settings.mascot.colorNavy': '深蓝色', + 'settings.mascot.colorYellow': '黄色', + 'settings.mascot.libraryUnavailable': 'OpenHuman 资源库不可用', 'settings.mascot.title': 'OpenHuman', - 'settings.developerMenu.mcpServer.title': 'MCP Server', - 'settings.developerMenu.mcpServer.desc': 'Configure external MCP clients to connect to OpenHuman', - 'settings.mcpServer.title': 'MCP Server', - 'settings.mcpServer.toolsSectionTitle': 'Available Tools', + 'settings.developerMenu.mcpServer.title': 'MCP 服务器', + 'settings.developerMenu.mcpServer.desc': '配置外部 MCP 客户端以连接到 OpenHuman', + 'settings.mcpServer.title': 'MCP 服务器', + 'settings.mcpServer.toolsSectionTitle': '可用工具', 'settings.mcpServer.toolsSectionDesc': - 'Tools exposed via the MCP stdio server when running openhuman-core mcp', - 'settings.mcpServer.configSectionTitle': 'Client Configuration', - 'settings.mcpServer.configSectionDesc': - 'Select your MCP client to generate the correct configuration snippet', - 'settings.mcpServer.copySnippet': 'Copy to Clipboard', - 'settings.mcpServer.copied': 'Copied!', - 'settings.mcpServer.openConfigFile': 'Open Config File', + '运行 openhuman-core mcp 时通过 MCP stdio 服务器暴露的工具', + 'settings.mcpServer.configSectionTitle': '客户端配置', + 'settings.mcpServer.configSectionDesc': '选择你的 MCP 客户端以生成对应的配置代码片段', + 'settings.mcpServer.copySnippet': '复制到剪贴板', + 'settings.mcpServer.copied': '已复制!', + 'settings.mcpServer.openConfigFile': '打开配置文件', 'settings.mcpServer.binaryPathNotFound': - 'OpenHuman binary not found. If running from source, build with: cargo build --bin openhuman-core', - 'settings.mcpServer.openConfigError': 'Failed to open config file', + '未找到 OpenHuman 二进制文件。如果使用源码运行,请执行:cargo build --bin openhuman-core', + 'settings.mcpServer.openConfigError': '打开配置文件失败', 'settings.mcpServer.clientClaudeDesktop': 'Claude Desktop', 'settings.mcpServer.clientCursor': 'Cursor', 'settings.mcpServer.clientCodex': 'Codex', 'settings.mcpServer.clientZed': 'Zed', - 'settings.mcpServer.configFilePath': 'Config file', - 'settings.mcpServer.clientSelectorAriaLabel': 'MCP client selector', + 'settings.mcpServer.configFilePath': '配置文件', + 'settings.mcpServer.clientSelectorAriaLabel': 'MCP 客户端选择器', }; export default zhCN5; diff --git a/docs/SECURITY_AUDIT.md b/docs/SECURITY_AUDIT.md new file mode 100644 index 000000000..8db0453a3 --- /dev/null +++ b/docs/SECURITY_AUDIT.md @@ -0,0 +1,211 @@ +# OpenHuman Security Audit — Architecture & Data Flow Analysis + +> Date: 2026-05-21 +> Author: JAYcodr (fork analysis, not an official audit) +> Scope: Architecture overview, trust boundaries, credential flow, attack surface + +--- + +## 1. System Overview + +OpenHuman is a desktop AI assistant with a **Rust core** running in-process inside a Tauri desktop host, and a **React/TypeScript frontend**. Communication between frontend and core happens via two channels: + +| Channel | Protocol | Auth | +|---|---|---| +| Primary | Socket.IO (bidirectional streaming) | Session-baked connection auth | +| Secondary | HTTP JSON-RPC | Basic Auth (`WWW-Authenticate` realm) | + +**No sidecar binary** — core runs as a tokio task inside the Tauri process (`core_process.rs`). + +--- + +## 2. Module Map + +### Core (`src/openhuman/`) — 66 domains + +| Category | Domains | +|---|---| +| Agent | `agent`, `agent_experience`, `agent_tool_policy` | +| Memory | `memory` (stm_recall, docs), `embeddings`, `learning`, `workspace` | +| Skills | `skills` (metadata-only), `mcp_client`, `mcp_clients`, `mcp_server`, `composio` | +| Channels | `channels` (dispatch), `telegram`, `discord`, `whatsapp_data`, `webview_accounts` | +| Infrastructure | `http_host`, `socket` (Socket.IO server), `runtime_node`, `runtime_python` | +| Business Logic | `billing`, `credentials`, `vault`, `encryption`, `notifications`, `webhooks`, `approval`, `cron`, `meet`, `meet_agent`, `team`, `threads`, `todos` | +| UI-adjacent | `accessibility`, `autocomplete`, `screen_intelligence`, `voice` | +| Other | `config`, `health`, `heartbeat`, `doctor`, `migration`, `update`, `security`, `prompt_injection` | + +### Transport (`src/core/`) + +| File | Role | +|---|---| +| `src/core/jsonrpc.rs` | JSON-RPC over HTTP, method dispatch | +| `src/core/socketio.rs` | Socket.IO server, `WebChannelEvent` struct for streaming | +| `src/core/auth.rs` | HTTP Basic Auth handler | +| `src/openhuman/http_host/rpc.rs` | JSON-RPC endpoint (`list()` function) | +| `src/openhuman/http_host/auth.rs` | `WWW-Authenticate` header, `unauthorized_response()` | + +### Event Bus (`src/core/event_bus/`) + +Typed pub/sub + in-process typed request/response: + +```text +publish_global(DomainEvent) → fire-and-forget broadcast +register_native_global(method, handler) → one-to-one typed dispatch +request_native_global(method, req) → call and wait for response +``` + +**Domain events:** `agent`, `memory`, `channel`, `skill`, `tool`, `webhook`, `mcp_client`, `system`, `approval`, `cron`, `triage` + +--- + +## 3. Credential & Token Flows + +### Core RPC Auth + +- HTTP JSON-RPC protected by **HTTP Basic Auth** +- Realm: `"OpenHuman Hosted Directory"` +- Per-launch bearer token stored in `OPENHUMAN_CORE_TOKEN` env var +- Frontend obtains bearer via `invoke('core_rpc_token')` Tauri command + +### Stored Credentials + +- `credentials` domain manages credential storage +- `encryption` domain handles at-rest encryption +- `auth-profiles.json` — auth data referenced by `settings.ai.apiKeysEncrypted` i18n key + +### MCP Server Auth + +- Composio API key stored via `settings.composio.apiKeyStoredPlaceholder` +- MCP client config (Claude Desktop, Cursor, Codex, Zed) generated in settings panel + +--- + +## 4. Trust Boundaries & Attack Surface + +### Boundary 1: External Channels (Telegram, Discord, WhatsApp, etc.) + +- Inbound messages from third-party messaging platforms flow through `channels/runtime/dispatch.rs` +- Each provider scanner runs as native CDP/scraping — **no JS injection** in migrated providers +- `ChannelInboundMessage` event published to event bus + +**Risk:** Third-party message content is untrusted. Prompt injection possible if message content is rendered or echoed without sanitization. The `prompt_injection` domain exists as a guard. + +### Boundary 2: MCP Tool Bridge (`mcp_client/`, `mcp_clients/`) + +- External MCP servers connect via stdio or HTTP +- Tools exposed through `tool_registry` +- `McpClientToolExecuted` events published + +**Risk:** MCP tools are external services. Tool output flows back into agent context. No obvious output sanitization in the tool execution path. + +### Boundary 3: Skill Runtime (Removed) + +- QuickJS / `rquickjs` runtime was **removed** (PR #1061) +- `src/openhuman/skills/` is now metadata-only +- No dynamic code execution from skill packages + +**Risk:** Significantly reduced vs. prior architecture. + +### Boundary 4: Local File System Access + +- `workspace`, `vault`, `webview_accounts` domains have file system access +- `screen_intelligence`, `accessibility` domains capture screen content +- Memory stored via `memory` domain + +**Risk:** Screen capture and file access are high-privilege operations. Controlled by macOS permissions (Accessibility, Screen Recording). + +### Boundary 5: MCP Server Config File + +- Settings panel generates `~/.config/openhuman/mcp.json` for external MCP clients +- Config written via `settings.mcpServer.openConfigFile` / `writeFile` +- Path exposed via `settings.mcpServer.configFilePath` + +**Risk:** If `mcp.json` is world-readable, token theft possible. Worth auditing file permissions on the config directory. + +--- + +## 5. Data Flows + +### Agent Turn (primary AI interaction) + +```text +External message → channels/runtime/dispatch.rs + → request_native_global("agent.run_turn", AgentTurnRequest) + → agent/bus.rs: run_tool_call_loop() + → tool_registry → SkillExecution events + → on_delta mpsc channel → WebChannelEvent (Socket.IO) + → frontend (SocketIOMCPTransportImpl) +``` + +### Memory Recall + +```text +Tool call: memory.recall → memory/stm_recall/recall.rs: stm_recall() + → MemoryRecalled event on event bus + → consumed by skill/mcp_client subscribers +``` + +### Credential Setup + +```text +Frontend settings → core RPC (JSON-RPC over HTTP + Basic Auth) + → credentials domain → encryption domain + → stored to auth-profiles.json +``` + +--- + +## 6. Security Observations (Not Exhaustive) + +### Areas Worth Auditing + +1. **Prompt injection from channel messages** — `prompt_injection` domain exists; need to verify it's applied to all channel inbound paths and not just chat UI +2. **MCP tool output sanitization** — external MCP tool output flows into agent context without obvious filtering +3. **Config directory permissions** — `~/.config/openhuman/` and `mcp.json` permission model not reviewed +4. **Credential encryption** — `encryption` domain used for at-rest encryption; key management model unclear +5. **WebView CSP** — embedded webviews (Telegram, Discord, etc.) loaded under CEF — need to verify CSP headers and iframe restrictions +6. **`OPENHUMAN_CORE_TOKEN` in process env** — bearer token in env var; visible via `/proc/self/environ` on Linux or process inspection on macOS +7. **No rate limiting observed** on HTTP JSON-RPC endpoint + +### Positive Signals + +- QuickJS skill runtime removed — large attack surface eliminated +- CEF webviews for migrated providers have **zero injected JS** — good isolation +- MCP server stdio transport provides sandboxing for external tools +- `security` domain exists — may contain hardening measures not reviewed here + +--- + +## 7. Recommended Next Steps (for Maintainers) + +- [ ] Audit `prompt_injection` domain coverage — is it applied to all channel inbound paths? +- [ ] Document `encryption` domain key management +- [ ] Check file permissions on `~/.config/openhuman/` +- [ ] Add rate limiting to HTTP JSON-RPC endpoint +- [ ] Document MCP tool output handling expectations +- [ ] Review `OPENHUMAN_CORE_TOKEN` lifetime and exposure scope + +--- + +## 8. RPC Method Reference + +JSON-RPC methods follow `domain_operation` pattern: + +```text +memory_recall_memories +memory_recall_context +thread_turn_state_lifecycle +wallet_setup_round_trips_status +tool_registry_lists_and_gets_entries +``` + +Native (event bus) methods: + +```text +agent.run_turn → agent/bus.rs +memory.sync → memory/bus.rs +``` + +--- + +*This document is an independent analysis, not an official security assessment.* \ No newline at end of file