Back to skill

Security audit

Hermes Memory Bridge

Security checks for vulnerabilities and agentic risk

Overview

This is a real memory bridge, but it needs Review because it can persistently process unauthenticated local command files and contains a task-command code injection path.

Install only after review if you are comfortable with a user-level background watcher that reads and writes Hermes/WorkBuddy memory, processes local command files automatically, and can modify TickTick tasks. Before use, disable the LaunchAgent by default, restrict ~/.hermes/shared permissions, remove the python -c task handlers or make them use safe argument passing, authenticate signal files, and require confirmation for memory writes and task changes.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
Findings (5)

T06 · System Persistence

Error
Location
install_v2.sh:86
Finding

Persistent launch agent with automatic restart

Content
View full analysis
"$PLIST_PATH" << EOF Label com.workbuddy.hermes-watcher ProgramArguments /usr/bin/python3 ${SKILL_DIR}/event_watcher.py WorkingDirectory ${SHARED_DIR} EnvironmentVariables BRIDGE_LOG_LEVEL INFO RunAtLoad KeepAlive StandardOutPath /tmp/hermes-watcher.log StandardErrorPath /tmp/hermes-watcher.err ProcessType Background EOF ``` ### Technical Analysis The installer creates a macOS LaunchAgent definition under the user's `~/Library/LaunchAgents` directory. `RunAtLoad` causes the watcher to start whenever the LaunchAgent is loaded, while `KeepAlive` instructs launchd to restart it after termination. A continuously running watcher is relevant to the advertised event-driven functionality, and the script only prints the `launchctl load` command rather than executing it automatically. Nevertheless, this is an explicit persistence mechanism and is not required for manual or on-demand synchronization. The persistent service executes `event_watcher.py` directly from the Skill directory, so subsequent modification or replacement of that fi ...[truncated 889 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
task_processor.py:202
Finding

Arbitrary Python code injection through task parameters

Content
View full analysis
dict: """在滴答清单创建任务""" title = params.get("title", "") if not title: return {"success": False, "error": "缺少 title 参数"} # 优先使用 ticktickpower skill try: result = _run_cmd([ sys.executable, "-c", f"from ticktickpower import TickTick; t = TickTick(); " f"print(t.add_task(title='{title}', project_id='5a4ba4bce775913530602288'))" ], timeout=15) if result.get("success"): try: return {"success": True, "task": json.loads(result["stdout"])} except json.JSONDecodeError: return {"success": True, "raw": result["stdout"]} return {"success": False, "error": result.get("error") or result.get("stderr") or "创建失败"} except Exception: pass return { "success": False, "error": "ticktickpower 未安装或不可用", "hint": "请在 WorkBuddy 中手动创建任务或确保 ticktickpower skill 已激活", "title": title, } def _complete_task(params: dict) -> dict: """标记滴答清单任务完成""" task_id = params.get("task_id", "") if not task_id: return {"success": False, "error": "缺少 task_id 参数"} try: result = _run_cmd([ sys.executable, "-c", f"from ticktickpower import TickTick; t = TickTick(); t.complete_task('{task_id}')" ], timeout=10) return {"success": result.get("success", False), "raw": result} except Exception as e: return {"success": False, "error": str(e)} ``` ### Technical Analysis The `title` and `task_id` parameters are inserted directly into Python source that is passed to `python -c`. Avoiding `shell=True` does not prevent this vulnerability because the injection occurs in the Python par ...[truncated 1640 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
event_watcher.py:112
Finding

Unauthenticated shared-file command channel

Content
View full analysis
list[dict]: if not SIGNAL_DIR.exists(): return [] processed = _read_processed() new_signals = [] for fpath in sorted(SIGNAL_DIR.glob("sig_*.json"), key=lambda f: f.stat().st_mtime): sig = _safe_read(fpath) if sig is None: continue sid = sig.get("id", "") if sid in processed: continue if sig.get("source") != source_filter: continue new_signals.append(sig) processed.add(sid) if new_signals: _write_processed(processed) return new_signals ``` ```python def _process_single_signal(sig: dict) -> None: import importlib signal_id = sig.get("id", "") signal_type = sig.get("type", "") signal_data = sig.get("data", {}) command_type = signal_data.get("command", "") if not command_type: type_to_command = { "task_done": "echo", "sync": "sync_session", "config_change": "ack", "ack": "ack", "feedback": "ack", } command_type = type_to_command.get(signal_type, signal_type) params = signal_data.get("params", signal_data) try: task_processor = importlib.import_module("task_processor") result = task_processor.process_command(command_type, params, signal_id) except Exception as e: logger.error(f"task_processor 执行失败: {e}") result = {"success": False, "error": str(e)} ``` ### Technical Analysis The watcher treats a JSON message as trusted solely when its attacker-controlled `source` field equals `"Hermes"`. It does not verify a signature, shared secret, operating-system identity, file owner, file permissions, inode type, or prod ...[truncated 1444 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

Error
Location
task_processor.py:147
Finding

Untrusted cross-agent content can poison persistent WorkBuddy memory

Content
View full analysis
dict: """同步会话记忆(生成会话摘要写到 WorkBuddy 记忆)""" topic = params.get("topic", "通用会话") summary = params.get("summary", "") notes = params.get("notes", "") if not summary: return {"success": False, "error": "缺少 summary 参数"} memory_dir = WORKBUDDY_MEMORY_DIR if not memory_dir or not memory_dir.exists(): wb_root = Path.home() / "WorkBuddy" if wb_root.exists(): try: latest = max( [d for d in wb_root.iterdir() if d.is_dir() and d.name.isdigit()], key=lambda d: d.name, ) memory_dir = latest / ".workbuddy" / "memory" except (ValueError, PermissionError): pass if not memory_dir: return {"success": False, "error": "无法定位 WorkBuddy 记忆目录"} today = datetime.now().strftime("%Y-%m-%d") fname = memory_dir / f"{today}.md" entry = f"\n## [{_ts()}] {topic}\n\n{summary}\n" if notes: entry += f"\n**备注**: {notes}\n" try: FEEDBACK_DIR.mkdir(parents=True, exist_ok=True) existing = "" if fname.exists(): existing = fname.read_text(encoding="utf-8") fname.write_text(existing + entry, encoding="utf-8") return {"success": True, "file": str(fname), "entry_preview": summary[:100]} except PermissionError: return {"success": False, "error": "权限不足,无法写入记忆文件"} except Exception as e: return {"success": False, "error": str(e)} ``` ### Technical Analysis The `topic`, `summary`, and `notes` fields originate from signal data and are written directly into a persistent WorkBuddy Markdown memory file. The operation does not require user confirmation, mark the content as untrusted, or isolate i ...[truncated 1307 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
install_v2.sh:29
Finding

Private command and message files lack explicit restrictive permissions

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (76)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

If the skill truly includes an undeclared network-backed weather lookup or other hidden external access, that is a material capability mismatch with security impact because it expands the data flow outside the local bridge model. Hidden network access is dangerous in an agent skill because users may authorize it as a local-memory utility while it can reach external services and leak prompts or metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

If the skill truly includes an undeclared network-backed weather lookup or other hidden external access, that is a material capability mismatch with security impact because it expands the data flow outside the local bridge model. Hidden network access is dangerous in an agent skill because users may authorize it as a local-memory utility while it can reach external services and leak prompts or metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

If the skill truly includes an undeclared network-backed weather lookup or other hidden external access, that is a material capability mismatch with security impact because it expands the data flow outside the local bridge model. Hidden network access is dangerous in an agent skill because users may authorize it as a local-memory utility while it can reach external services and leak prompts or metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding

If the skill truly includes an undeclared network-backed weather lookup or other hidden external access, that is a material capability mismatch with security impact because it expands the data flow outside the local bridge model. Hidden network access is dangerous in an agent skill because users may authorize it as a local-memory utility while it can reach external services and leak prompts or metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
86% confidence
Finding

If the skill truly includes an undeclared network-backed weather lookup or other hidden external access, that is a material capability mismatch with security impact because it expands the data flow outside the local bridge model. Hidden network access is dangerous in an agent skill because users may authorize it as a local-memory utility while it can reach external services and leak prompts or metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

If the skill truly includes an undeclared network-backed weather lookup or other hidden external access, that is a material capability mismatch with security impact because it expands the data flow outside the local bridge model. Hidden network access is dangerous in an agent skill because users may authorize it as a local-memory utility while it can reach external services and leak prompts or metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

If the skill truly includes an undeclared network-backed weather lookup or other hidden external access, that is a material capability mismatch with security impact because it expands the data flow outside the local bridge model. Hidden network access is dangerous in an agent skill because users may authorize it as a local-memory utility while it can reach external services and leak prompts or metadata.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

If the skill truly includes an undeclared network-backed weather lookup or other hidden external access, that is a material capability mismatch with security impact because it expands the data flow outside the local bridge model. Hidden network access is dangerous in an agent skill because users may authorize it as a local-memory utility while it can reach external services and leak prompts or metadata.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The watcher treats Hermes-originated JSON files as actionable commands and passes attacker-controlled command_type and params into task_processor.process_command(), then writes feedback and ACKs automatically. In a skill described as a memory bridge/event listener, this crosses into implicit command execution on untrusted cross-agent input, creating a high-risk trust boundary violation that could trigger unintended actions depending on what task_processor supports.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · install_v2.sh (reported line 58)May include surrounding context.

sh
# ─── 3. 创建 Hermes 环境变量配置(可选)────────────────────────────
echo ""
echo "⚙️  配置环境变量..."
ENV_FILE="$HERMES_HOME/.env"
if [ -f "$ENV_FILE" ]; then
    echo "   ℹ️  $ENV_FILE 已存在,跳过"
else

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill launches subprocesses and later feeds them dynamically constructed Python code for TickTick operations, which is a powerful execution primitive not justified by a memory-sync role. In this context, the helper enables external actions and compounds risk because untrusted command parameters are interpolated into code strings elsewhere in the file.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
93% confidence
Finding

This skill is described as a memory bridge, but it can create, complete, and list external TickTick tasks, extending its authority beyond the stated purpose. That mismatch increases the chance that users or higher-level agents will grant or invoke it under false assumptions, enabling unintended side effects in external systems.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill documents shell execution, environment-variable use, and read/write access to persistent files across two systems, but declares no explicit tool scope or permission boundaries. In an agent setting this can lead to overbroad invocation and unintended execution of file- and shell-capable actions with user data or external side effects.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger list includes broad phrases like memory sync, search, environment variables, error handling, and evolution-related terms without clear boundaries, making accidental or adversarial activation more likely. In an agentic environment, ambiguous triggers can cause the skill to run write-capable or shell-backed workflows when the user did not intend to invoke them.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill advertises bidirectional memory synchronization and explicitly notes that WorkBuddy can write to Hermes memory files, but it does not present a clear user-facing warning about persistent data modification. In context this is especially dangerous because the skill bridges two memory stores and could permanently alter notes, profiles, or shared state across systems.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documented commands can create, complete, and list third-party tasks, but there is no user-facing warning that these actions modify external service data. In an agent workflow, undocumented write effects against task systems can cause silent state changes, fraud, or loss of task integrity.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

Referencing a plist-backed LaunchAgent reinforces that the skill sets up operating-system persistence rather than one-shot execution. In this skill’s context, persistence increases risk because the bridge can continue handling signals, tasks, and file events without immediate user awareness.

Content

Scanner excerpt · SKILL.md (reported line 205)May include surrounding context.

md
bash ~/.workbuddy/skills/hermes-memory-bridge/install_v2.sh

# 启动守护进程
launchctl load ~/Library/LaunchAgents/com.workbuddy.hermes-watcher.plist

# 查看日志
tail -f /tmp/hermes-watcher.log

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

Referencing a plist-backed LaunchAgent reinforces that the skill sets up operating-system persistence rather than one-shot execution. In this skill’s context, persistence increases risk because the bridge can continue handling signals, tasks, and file events without immediate user awareness.

Content

Scanner excerpt · SKILL.md (reported line 205)May include surrounding context.

md
bash ~/.workbuddy/skills/hermes-memory-bridge/install_v2.sh

# 启动守护进程
launchctl load ~/Library/LaunchAgents/com.workbuddy.hermes-watcher.plist

# 查看日志
tail -f /tmp/hermes-watcher.log

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documented trigger section repeats broad, natural-language phrases that could overlap ordinary conversation and unintentionally activate the skill. Because this skill can write persistent memory, send tasks, and start bridge workflows, accidental invocation raises meaningful integrity and privacy risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file’s descriptive docstrings and runtime messages are written exclusively in Chinese, including startup, shutdown, and error-related output. This imposes a specific language on users and operators without any opt-in, fallback, or justification that the skill is intended only for a Chinese-language environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file contains natural-language descriptions and command-line prompts entirely in Chinese, including the module docstring and usage/help text. The skill does not offer an opt-in language choice or explain that it is intentionally limited to a Chinese-speaking context, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

User-visible prompts such as message entry, reply entry, status notifications, and usage instructions are all hard-coded in Chinese. Because the skill does not provide any mechanism for language selection or user opt-in, it imposes a specific locale on all users.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module docstring and all user-facing help/CLI messages are written only in Chinese, which effectively imposes a specific language on users. The file does not provide an opt-in, alternative locale, or justification that this skill is intended only for a Chinese-speaking or region-specific environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code presents user-facing descriptions, errors, status messages, and help text entirely in Chinese, which enforces a specific language/locale on all users. The file does not offer any opt-in, fallback, or documented justification for the locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring and all user-facing help/status/error strings in this file are written exclusively in Chinese, indicating the skill is designed to communicate in a fixed language. There is no indication anywhere in the file that users can choose another language or that the Chinese-only behavior is a documented regional constraint.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.