Back to skill

Security audit

Agent Office

Security checks for vulnerabilities and agentic risk

Overview

This skill matches its local multi-agent office purpose, but it exposes powerful local agents through under-protected HTTP, mutable runtime installs, broad tool access, and unsafe path handling.

Install only if you are comfortable running persistent local AI workers that can call local CLIs, access workspaces, and potentially run shell-enabled DeerFlow tasks. Use it in a dedicated, low-sensitivity workspace, avoid external upstream URLs unless you fully trust them, keep MEMORY_CLI disabled for sensitive work, and do not use custom worker IDs or DeerFlow runtime updates without reviewing the exact paths and code source.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
worker_server.py:220
Finding

Unauthenticated HTTP Task API Can Invoke Privileged Local Agents

Content
View full analysis
Remediation
View remediation
` for task submission, task status, task results, and state endpoints. 3. Store tokens with restrictive filesystem permissions and never place them in logs. 4. Reject requests with unexpected `Origin` headers and require `Content-Type: application/json`. 5. Generate task identifiers exclusively on the server; do not accept caller-selected IDs. 6. Add maximum request-body sizes, task concurrency limits, and rate limits. 7. Run each worker under a restricted operating-system identity or sandbox. 8. Restrict each engine to the minimum filesystem and command capabilities required for its role. 9. Consider using a Unix-domain socket with filesystem permissions instead of an unauthenticated TCP endpoint. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
worker_server.py:733
Finding

External Worker Bridge Can Disclose Tasks and Shared Memory to Arbitrary Destinations

Content
View full analysis
str: raw = (url or "").strip() if not raw and port: raw = f"http://127.0.0.1:{port}" if not raw: return "" if "://" not in raw: raw = f"http://{raw}" return raw.rstrip("/") ``` ```python def _build_external_description(self, title, description, memory_matches=None): sections = [ f"这是 Agent Office 转发给外部员工 {self.worker_name} 的任务。", "请保持你原有身份、设定和长期记忆,不要把自己重置成新的角色。", "", "任务标题:" + (title or "(无标题)"), "任务描述:" + (description or "(无描述)"), "", "办公室补充上下文:", self._build_shared_memory_context(memory_matches), ] return "\n".join(sections).strip() ``` ```python def _external_request(self, method, path, payload=None, timeout=15): if not self.external_upstream_url: raise RuntimeError("external upstream url 未配置") url = f"{self.external_upstream_url}{path}" body = None headers = {} if payload is not None: body = json.dumps(payload, ensure_ascii=False).encode("utf-8") headers["Content-Type"] = "application/json" req = request.Request(url, data=body, headers=headers, method=method.upper()) with request.urlopen(req, timeout=timeout) as resp: raw = resp.read().decode("utf-8") return resp.status, json.loads(raw) if raw else {} ``` ```python _, submit_payload = self._external_request( "POST", "/tasks", { "title": title or "Agent Office 转发任务", "description": forwarded_description, }, timeout=min(15, self.external_timeout), ) ``` ### Technical Analysis The external-worker feature is documented primarily as a b ...[truncated 1966 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/add_worker.py:572
Finding

Unvalidated Worker Identifiers Allow Directory Traversal and Recursive Deletion

Content
View full analysis
Path: return runtime_homes_root(base_dir) / worker_id ``` ```python worker_dir = OFFICE_DIR / "workers" / wid if worker_dir.exists(): import shutil shutil.rmtree(worker_dir) print(f"✅ 目录已删除: {worker_dir}") if engine == "deerflow": home_dir = Path(worker.get("deerflow_home") or worker_home(wid)) if home_dir.exists(): import shutil shutil.rmtree(home_dir) print(f"✅ DeerFlow home 已删除: {home_dir}") ``` ### Technical Analysis The command-line option `--worker-id` is used directly as a filesystem path component. It is not validated against an identifier grammar and is not rejected when it contains path separators, `..` components, or an absolute path. With `pathlib`, joining a base path with an absolute child discards the base. Relative traversal components can likewise resolve outside the intended worker directory. The escaped path is persisted in state and is later trusted during worker removal. The removal logic calls `shutil.rmtree()` without resolving the target and checking that it remains under the expected office root. For DeerFlow workers, the persisted `deerflow_home` value is also used directly as a recursive-deletion target. ### Attack Path 1. An attacker or unsafe automation invokes worker creation with a crafted value such as `--worker-id ../../target`. 2. ...[truncated 1012 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
deerflow_runtime.py:79
Finding

Mutable DeerFlow Runtime Is Retrieved and Executed Without Revision Verification

Content
View full analysis
dict[str, str]: base_dir = office_dir() shared_root = base_dir / "deerflow-runtime" root = runtime_root(base_dir) backend_dir = runtime_backend_dir(base_dir) python_bin = runtime_python(base_dir) shared_root.mkdir(parents=True, exist_ok=True) missing = missing_prerequisites() if missing: raise RuntimeError( "DeerFlow 自动安装缺少依赖: " + ", ".join(missing) ) if not root.exists(): _run_checked(["git", "clone", "--depth=1", DEERFLOW_REPO_URL, str(root)]) elif update: _run_checked(["git", "-C", str(root), "pull", "--ff-only"]) if not backend_dir.exists(): raise RuntimeError(f"DeerFlow backend 目录缺失: {backend_dir}") if update or not python_bin.exists(): _run_checked(["uv", "sync"], cwd=backend_dir) ``` ### Technical Analysis The Skill clones the current head of a remote Git repository and installs its dependencies with `uv sync`. The effective runtime payload can therefore change after this Skill has been reviewed. The source URL is controlled through `AGENT_OFFICE_DEERFLOW_REPO_URL`, and no origin allowlist is enforced. The implementation does not pin an audited commit, verify a signed tag, validate a commit hash, check a lockfile digest, or require approval for the exact revision being installed. The update path performs `git pull --ff-only`, which protects against non-fast-forward history changes but does not establish that the new commit is trusted. Fetched DeerFlow code is later imported and executed by `deerflow_runtime_runner.py` ...[truncated 1169 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
deerflow_runtime.py:174
Finding

DeerFlow Agents Receive Host Bash, Network Tools, and Writable Host Mounts

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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 (79)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/add_worker.py --list-cli-profiles

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/add_worker.py --list-cli-profiles

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This code forwards both task descriptions and shared-memory snippets to an external worker while also encouraging retention of prior long-term memory. In an office-worker setting, that combination significantly increases the chance of data leakage, cross-context contamination, and uncontrolled persistence outside the local environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README explicitly states that adding a deerflow worker will automatically install or reuse a shared runtime, which implies network access, code retrieval, dependency installation, and persistent filesystem changes. In an agent skill context, undocumented or weakly warned side effects can cause users to execute setup steps that modify their machine state and pull third-party code without fully informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README says shared memory context is injected when forwarding tasks to external workers, but it does not present this as a clear security/privacy warning. This can expose sensitive local context, prompts, or internal state to an upstream service that may be separately configured, less trusted, or operated with broader retention/logging than the office layer.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares substantial capabilities—shell execution, local file read/write, environment access, network use, and background worker management—but does not define any explicit tool scope such as permissions or allowed-tools. This creates an authorization ambiguity where an invoking agent may grant broader-than-necessary access, increasing the chance of unintended filesystem changes, process spawning, or network interactions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill description states that it manages local HTTP workers, writes under ~/.hermes/office, supports external and CLI engines, and can use shared runtimes, but it does not prominently warn that it will spawn background services, bind ports, persist state, and potentially fetch/update external code. Users may invoke it without understanding the system-impacting behavior, reducing informed consent for risky operations.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documented search/trigger keywords include broad phrases like 'agent office', 'office worker', and 'AI employee', which can overlap with ordinary user requests. Because this skill can create workers, write files, and start HTTP services, accidental invocation is more dangerous than with a read-only skill and could lead to unintended local changes or background processes.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

The skill intentionally creates and maintains persistent state under ~/.hermes/office, including worker identities, configs, logs, and status. While persistence is core to the feature, it still introduces security and privacy risk because long-lived local state and background workers can outlast the initiating session, accumulate sensitive task data, and be reused unexpectedly.

Content

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

Step 2:创建目录

bash
mkdir -p ~/.hermes/office/workers/{worker_id}/logs

Step 3:生成 SOUL.md

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · deerflow_runtime.py (reported line 67)May include surrounding context.

python
def _run_checked(cmd: list[str], cwd: Path | None = None) -> subprocess.CompletedProcess:
    result = subprocess.run(
        cmd,
        cwd=str(cwd) if cwd else None,
        capture_output=True,

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code automatically clones and optionally updates executable code from a remote Git repository at runtime, then prepares its Python environment with uv sync. That creates a software supply-chain risk: compromise of the repo, dependency set, environment variables, or network path could result in unreviewed code being fetched and later executed on the user's machine.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The clone/pull and dependency-sync path performs network access and modifies the local system state without any user confirmation or disclosure in this file. Even if intended for convenience, silent installation/update behavior is risky in an agent framework because users may not expect code retrieval, environment creation, or package changes as a side effect of adding a worker.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file writes Chinese-only agent instructions such as 你是 ... and other role guidance into SOUL.md. This enforces a specific language for downstream agent behavior without presenting a language choice or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The generated runtime config enables broad capabilities including web access, file read/write, and especially host bash execution via a local sandbox provider with allow_host_bash: true. In the context of a 'local AI employee' system that auto-creates autonomous workers, this materially increases the chance of arbitrary command execution, data exfiltration, persistence, or destructive host actions if a prompt, tool call, or upstream runtime is compromised.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The worker configuration silently grants powerful capabilities including file write access and host bash execution, which exceed a typical low-risk 'office worker' expectation. In an autonomous multi-agent setting, undisclosed command execution and filesystem modification significantly raise the blast radius of prompt injection, model misuse, or logic errors.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

When JSON parsing fails, the code constructs multiple user-facing fallback strings in Chinese, including the default team summary and scope notes. This imposes a specific language on output regardless of user preference, and the file does not provide a language choice or justify a region-specific 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 file’s display name, description, slot labels, and all step titles/descriptions are written entirely in Chinese, which imposes a specific language on use of the skill. There is no indication that users can opt into another language or that the locale restriction is required for a region-specific purpose, which fits the language/locale policy-violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The display name, description, slot labels, and all step titles/descriptions are written exclusively in Chinese, which imposes a specific language on users and downstream workers. The file does not offer any language choice or document that this flow is intentionally limited to a Chinese-language context, so it creates a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code initializes and rewrites persistent JSON state on disk, including office_state.json and later worker config files, but provides no user-facing warning that running the script will modify files under the Hermes office directory. The script prints general progress messages, but those do not disclose the file-writing side effects before they occur.

Content

No source excerpt is available for this finding.

Tainted flow: 'STATE_FILE' from os.environ.get (line 42, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
88% confidence
Finding

Initial creation of the state file has the same environment-driven path risk as later saves: a hostile HERMES_OFFICE_DIR can redirect where the application initializes state. This can overwrite arbitrary writable files or create misleading state used by other parts of the system.

Content

Scanner excerpt · scripts/add_worker.py (reported line 158)May include surrounding context.

python
"available": list(range(5011, 5021))
            }
        }
        with open(STATE_FILE, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

Tainted flow: 'STATE_FILE' from os.environ.get (line 42, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
88% confidence
Finding

STATE_FILE is derived from HERMES_OFFICE_DIR, so an attacker controlling the environment can redirect state writes to arbitrary filesystem locations accessible to the process. In an agent-management skill that auto-creates and updates files, this can enable unauthorized overwrite of user data or poisoning of future worker state.

Content

Scanner excerpt · scripts/add_worker.py (reported line 169)May include surrounding context.

python
def save_state(data: dict):
    with open(STATE_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/add_worker.py (reported line 295)May include surrounding context.

python
# ── 层2:openclaw agents(仅openclaw/hermes)──────
    if engine in ("openclaw", "hermes"):
        try:
            r = subprocess.run(
                ["openclaw", "agents", "list", "--json"],
                capture_output=True, text=True, timeout=3
            )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/add_worker.py (reported line 421)May include surrounding context.

python
# ── 层2:openclaw agents(仅openclaw/hermes)──────
    if engine in ("openclaw", "hermes"):
        try:
            r = subprocess.run(
                ["openclaw", "agents", "list", "--json"],
                capture_output=True, text=True, timeout=3
            )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/add_worker.py (reported line 325)May include surrounding context.

python
return True

    if engine == "openclaw":
        if subprocess.run(["which", "openclaw"], capture_output=True).returncode == 0:
            v = subprocess.run(["openclaw", "--version"],
                             capture_output=True, text=True, timeout=3)
            print(f"✅ openclaw 已安装: {v.stdout.strip() or 'ok'}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/add_worker.py (reported line 326)May include surrounding context.

python
if engine == "openclaw":
        if subprocess.run(["which", "openclaw"], capture_output=True).returncode == 0:
            v = subprocess.run(["openclaw", "--version"],
                             capture_output=True, text=True, timeout=3)
            print(f"✅ openclaw 已安装: {v.stdout.strip() or 'ok'}")
            return True