Back to skill

Security audit

WorkflowHub

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent local workflow-memory tool, but its local web editor can save or delete persistent workflow instructions without authentication or origin checks.

Review before installing if you plan to use the local UI. Keep the server bound to 127.0.0.1, do not leave it running while browsing untrusted sites, inspect workflow files before approving reuse, and add authentication/origin checks and recoverable backups before relying on it for sensitive workflows.

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:134
Finding
Unauthenticated Localhost Workflow Poisoning<![CDATA[ ## Vulnerability Details **File Location**: `ui/server.py:134-153`, `ui/server.py:161-188`, `ui/server.py:265-275`; downstream execution path in `scripts/workflow_engine.py:194-224` **Vulnerability Type**: Persistent workflow instruction poisoning through an unauthenticated localhost API **Risk Level**: High ### Vulnerable Code #### Unauthenticated state-changing endpoint ```python 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.") ``` #### Arbitrary workflow creation, overwrite, and rename-based deletion ```python 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"]}) ``` #### No authentication, CSRF protection, Origin validation, or content-type enforcement ```python def read_json_body(self) -> dict | None: try: length = int(self.headers.get("Content-Le ...[truncated 4649 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Require authentication** - Generate a cryptographically random token when the server starts. - Require the token on every API request, especially all state-changing endpoints. - Avoid placing reusable authentication tokens in URLs where they may be logged. 2. **Enforce same-origin requests** - Reject state-changing requests unless the `Origin` header exactly matches the configured local UI origin. - Validate the `Host` header against the configured host and port. - Do not treat CORS headers alone as CSRF protection. 3. **Require the correct media type** - Accept workflow writes only when `Content-Type` is `application/json`. - Reject `text/plain`, form-encoded, multipart, and missing content types. - Apply strict request-body size limits before reading the body. 4. **Restrict network exposure** - Permit binding only to loopback addresses by default. - Require an explicit security override and authentication before allowing non-loopback `--host` values. - Clearly warn users if the server is exposed beyond localhost. 5. **Protect destructive operations** - Separate create, update, rename, and delete operations. - Require explicit confirmation and a visible diff before overwriting, renaming, or deleting a workflow. - Do not accept `_original_id` as an implicit deletion primitive in the general save endpoint. - Use atomic writes and retain recoverable backups or revision history. 6. **Treat workflow content as untrusted** - Clearly delimit stored workflow text in generated prompts. - State that stored steps are user-managed data, not system policy or authorization. - Reject or flag workflow instructions that attempt to override higher-priority instructions, obtain secrets, silently make external calls, or expand privileges. - Display the full execution brief or a meaningful diff before the user authorizes reuse. 7. **Add regression tests** - Verify that cross- ...[truncated 286 chars]
Vulnerability Patterns
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description emphasizes a reusable workflow memory system with retrieval, matching, reuse prompting, and save/update behavior around task execution. The supplied code chunk only captures a workflow draft from provided task text and outputs JSON. It does not show any persistence, lookup of existing workflows, matching against prior SOPs, or post-task save/update prompts. While workflow capture is related, the primary behavior in this code is materially narrower than the declared purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The code chunk only creates a starter JSON workflow file with placeholder fields and writes it to disk. While this is related to workflows in a broad sense, it does not implement the main declared behavior of remembering a user's way of working and using that memory during task execution. Its primary purpose is workflow file scaffolding, which is materially narrower and different from the described agent behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description implies a broader workflow-memory capability: storing reusable SOPs, checking them proactively, suggesting reuse, and prompting to save or update workflows around task execution. The actual code only reads an existing workflow JSON file and renders an execution brief via `render_execution_brief`. That is a narrow presentation utility, not a memory-management or workflow-reuse system. There are no undeclared dangerous capabilities, but the primary purpose is materially different and much narrower than the declared behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The code does implement part of the declared theme—persisting workflows/SOP-like data and updating existing ones. However, the description emphasizes a broader behavior: proactively consulting saved workflows before work begins, matching existing SOPs to current tasks, prompting for reuse, and prompting to save/update afterward. This code chunk only performs the save/update portion via command-line arguments and file I/O. It does not search existing workflows, perform matching, or handle the described proactive/prompting behaviors. Therefore the declared description materially overstates the actual behavior of this code chunk.

Lp3

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding
The skill describes behavior that relies on reading and writing workflow files, referencing environment-dependent paths like $CODEX_HOME, and serving a local UI, yet it declares no explicit tool scope or permissions boundary. That creates avoidable ambiguity about what file, environment, and network capabilities the skill may use, increasing the chance of over-broad access or unsafe invocation by the agent/runtime.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The skill enables implicit invocation without any visible trigger constraints, allowlist, or scope limitation. Because this skill is designed to influence workflow selection and memory reuse before starting tasks, automatic invocation could cause it to activate in overly broad contexts, leading to unintended use of stored SOPs, privacy exposure of prior work patterns, or prompt-routing behavior the user did not explicitly request.

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.

Static analysis

No suspicious patterns detected.