Back to skill

Security audit

SOP & Workflow memory skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent, but its local editor can change persistent agent workflow instructions through an unauthenticated local API.

Review before installing. The core idea is reasonable, but run the UI only on localhost, do not expose it with --host on a network, keep backups or version control for workflow JSON files, and inspect saved workflow steps before approving reuse because those files can steer future agent behavior.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

T02 · Agent Memory Poisoning

Error
Location
ui/server.py:128
Finding
Unauthenticated Local API Allows Persistent Workflow Instruction Poisoning<![CDATA[ ## Vulnerability Details **File Location**: `ui/server.py:128-178`, `ui/server.py:257-268`, and `scripts/workflow_engine.py:194-225` **Vulnerability Type**: Unauthenticated state-changing API, CSRF, and persistent Agent memory poisoning **Risk Level**: High ### Vulnerable Code The server exposes a state-changing workflow endpoint without authentication, CSRF protection, or request-origin validation: ```python # ui/server.py:128-139 def do_POST(self) -> None: parsed = urlparse(self.path) path = unquote(parsed.path) if path == "/api/workflows": return self.handle_save_workflow() if path == "/api/match": return self.handle_match_workflows() if path == "/api/capture-draft": return self.handle_capture_draft() if path == "/api/render-brief": return self.handle_render_brief() self.respond_error(HTTPStatus.NOT_FOUND, "Unknown endpoint.") ``` Attacker-supplied workflow content is validated only for a name and syntactically safe identifier, then written directly to the workflow library: ```python # ui/server.py:158-178 def handle_save_workflow(self) -> None: body = self.read_json_body() if body is None: return original_id = body.pop("_original_id", None) try: workflow = validate_workflow(body) destination = workflow_path(self.config.workflows_dir, workflow["id"]) except ValueError as exc: return self.respond_error(HTTPStatus.BAD_REQUEST, str(exc)) if original_id and original_id != workflow["id"]: try: old_path = workflow_path(self.config.workflows_dir, original_id) except ValueError as exc: return self.respond_error(HTTPStatus.BAD_REQUEST, str(exc)) if old_path.exists(): old_path.unlink() destination.write_text(json.dumps(workflow, indent=2) + "\n", encoding="utf-8") self.respond_json({"ok": True, "id": workflow["id"]}) ``` The request parser accepts JSON without requiring ...[truncated 6119 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Require authentication for all API endpoints** - Generate a cryptographically random token when the server starts. - Require the token in a custom request header for every API request. - Avoid placing long-lived credentials in workflow files or URLs. - Compare tokens using a constant-time comparison function. 2. **Implement CSRF protection** - Generate a per-session CSRF token. - Require it on every POST, PUT, PATCH, and DELETE request. - Reject state-changing requests without a valid token. 3. **Validate request origins** - Check the `Origin` header against the exact expected local UI origin. - Reject unexpected, missing, or opaque origins for state-changing requests. - Validate the `Host` header to reduce DNS rebinding exposure. - Do not use CORS response headers as a substitute for authentication. 4. **Enforce strict request formats** - Require `Content-Type: application/json`. - Reject simple cross-origin content types such as `text/plain`. - Validate the complete workflow against a strict schema. - Reject unknown fields such as `_original_id` unless they are explicitly expected and authorized. 5. **Limit request sizes** - Configure a small maximum request-body size appropriate for workflow JSON. - Return HTTP 413 before reading a body whose declared size exceeds the limit. - Limit workflow field lengths and the number of steps, keywords, and tools. 6. **Protect workflow integrity** - Use atomic writes through a temporary file in the same directory followed by a rename. - Refuse silent overwrites unless the client supplies the expected current version or content hash. - Keep revision history or backups so poisoned or accidentally deleted workflows can be restored. - Defend against symlink targets when reading, writing, or deleting workflow files. 7. **Treat stored workflow text as untrusted data** - Add an explicit boundary to generated briefs st ...[truncated 866 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
To the extent this finding highlights filesystem read/write behavior not reflected in declared permissions, it overlaps with a real security issue: the skill instructs persistence and workflow updates without an explicit capability declaration or boundary. That can lead to unintended data modification or overbroad file access if the host system infers permissions loosely from referenced scripts and paths.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
To the extent this finding highlights filesystem read/write behavior not reflected in declared permissions, it overlaps with a real security issue: the skill instructs persistence and workflow updates without an explicit capability declaration or boundary. That can lead to unintended data modification or overbroad file access if the host system infers permissions loosely from referenced scripts and paths.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding
To the extent this finding highlights filesystem read/write behavior not reflected in declared permissions, it overlaps with a real security issue: the skill instructs persistence and workflow updates without an explicit capability declaration or boundary. That can lead to unintended data modification or overbroad file access if the host system infers permissions loosely from referenced scripts and paths.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill explicitly references scripts, a local UI server, filesystem locations, and environment-based paths, but it declares no explicit tool scope or permission boundaries. That creates an authorization gap: an agent may read, write, or potentially expose workflow data more broadly than intended, especially because the skill persists reusable user process data and points to a runnable local server.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The default prompt is broadly phrased to activate workflow-memory behavior whenever the user mentions repeated tasks or ways of working, which can cause the skill to be invoked in ordinary planning conversations without clear user intent. Because implicit invocation is also enabled, this increases the chance of unsolicited retention-oriented behavior, such as checking or proposing saved SOPs in contexts where the user did not explicitly ask for memory use.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
## Interaction Boundary

The agent should not silently save a workflow without asking.

The intended pattern is:
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This code silently deletes an old workflow file during rename and writes the new workflow JSON without any confirmation prompt, log message, or warning beyond the module's generic description. Because these are direct file modification and deletion operations exposed by the server API, users are not explicitly informed when data will be overwritten or removed.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The DELETE handler unlinks the workflow file immediately and only reports success afterward. There is no confirmation step, warning comment/docstring, or user-facing disclosure in this file indicating that calling the endpoint permanently removes workflow data.

Description-Behavior Mismatch

Medium
Confidence
84% confidence
Finding
The manifest describes a skill for remembering a user's work style and proactively checking or suggesting reuse of saved workflows during tasks. This file implements a full editor UI that creates, updates, and deletes workflow records via POST and DELETE requests, which is broader than merely checking, suggesting reuse, or asking whether to save/update after a task.

Natural-Language Policy Violations

Low
Confidence
79% confidence
Finding
The file includes a dedicated Chinese-language section and an English section, but it does not state whether language selection is optional or whether the skill is intended for a specific locale. Under the policy rule, language handling should either offer explicit user choice or document the locale constraint and justification.

Description-Behavior Mismatch

Low
Confidence
86% confidence
Finding
The code fetches `/api/meta` and displays `state.meta.workflows_dir` directly in the UI, exposing the server-side filesystem path for stored workflows. Although low severity, disclosing internal path structure can aid reconnaissance by revealing deployment layout, usernames, mount points, or storage conventions that may help an attacker chain other issues.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
The document declares `lang="en"`, which is a natural-language locale choice applied to the entire UI. In the provided file, there is no indication that users can choose another language or that the English-only constraint is intentionally justified for a region-specific use case.

Static analysis

No suspicious patterns detected.