Back to skill

Security audit

Todo Boss

Security checks for vulnerabilities and agentic risk

Overview

This Telegram task tracker is coherent in purpose, but its task input handling can let a crafted /todo message execute local code.

Do not install this version where untrusted Telegram users can send /todo messages. The local persistence is expected for a task tracker, but the script should be fixed to pass user text as data rather than Python source, and the task log should have clear retention and access-control expectations.

Vulnerability Patterns
  • 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
  • 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
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
add_task.sh:22
Finding
Arbitrary Python Code Execution Through Unsafely Interpolated Task Input## Vulnerability Details **File Location**: `add_task.sh`, lines 22–33 **Vulnerability Type**: Python code injection through an unquoted heredoc **Risk Level**: High ```bash # JSON 기록 python3 - <<PY >> "$LOG" import json event = { "id": "$ID", "ts": "$TS", "title": "$TITLE", "owner": "$OWNER" if "$OWNER" else None, "due": "$DUE" if "$DUE" else None, "status": "draft" if (not "$OWNER" or not "$DUE") else "open", "raw": "$TEXT" } print(json.dumps(event, ensure_ascii=False)) PY ``` ### Technical Analysis The script places task attributes derived from user-controlled Telegram input directly into Python source code. The heredoc delimiter is unquoted, so Bash expands variables such as `TITLE`, `OWNER`, `DUE`, and `TEXT` before passing the resulting program to Python. These values are inserted between Python quotation marks without escaping them as Python string literals. An attacker can consequently terminate or modify the intended string expression and introduce an arbitrary Python expression. For example, input shaped like the following can cause a command to execute while Python evaluates the generated dictionary: ```text "+str(__import__('os').system('id'))+" ``` The resulting `title` expression would contain executable Python rather than an inert string: ```python "title": ""+str(__import__('os').system('id'))+"", ``` JSON serialization occurs only after the dynamically constructed Python source has already been parsed and executed. Therefore, the use of `json.dumps` does not mitigate this vulnerability. ### Attack Path 1. An attacker sends a crafted `/todo` message containing Python syntax in the task text. 2. The skill passes the full text as an argument to `add_task.sh`, as directed by `SKILL.md`. 3. The script derives `TITLE`, `OWNER`, `DUE`, and `TEXT` from that attacker-controlled argument. 4. Bash substitutes these values into the unquoted Python heredoc. 5. The substituted content changes the syntax or semantics of the ...[truncated 1102 chars]
Remediation
## Remediation Suggestions Do not construct executable source code by interpolating user-controlled data. 1. Pass values to a fixed Python program through positional arguments or environment variables: ```bash python3 - "$ID" "$TS" "$TITLE" "$OWNER" "$DUE" "$TEXT" <<'PY' >> "$LOG" import json import sys task_id, timestamp, title, owner, due, raw = sys.argv[1:] event = { "id": task_id, "ts": timestamp, "title": title, "owner": owner or None, "due": due or None, "status": "draft" if not owner or not due else "open", "raw": raw, } print(json.dumps(event, ensure_ascii=False)) PY ``` 2. Quote the heredoc delimiter (`<<'PY'`) so that Bash does not perform parameter, command, or arithmetic expansion within the Python program. 3. Keep all user data outside the Python source and allow `json.dumps` to serialize it as data. 4. Add regression tests covering quotation marks, backslashes, newlines, Unicode, shell metacharacters, and Python expressions. 5. Run the skill with least privilege and restrict its filesystem, credential, and network access to reduce the impact of any future injection flaw.
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Session Persistence

Medium
Category
Rogue Agent
Content
Derived state cache (optional): ~/.openclaw/workspace/data/todo/state.json

## Commands (Telegram)
- /todo <text> : create a task draft from free text
- /todo_done <id> : mark done
- /todo_list : list open tasks (grouped by owner, then due date)
- /todo_delegated : list tasks I assigned to others that are still open (include history)
Confidence
74% confidence
Finding
The skill persists task content and history in local JSONL/state files, including free-text user input, owners, due dates, and update history. In a Telegram-based workflow this can accumulate sensitive operational data indefinitely, and the append-only history increases exposure if the workspace is shared, backed up insecurely, or accessed by other skills/users without access controls.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The default follow-up questions are specified in Korean and the timezone is fixed to Asia/Seoul, but the skill does not state that it is intentionally Korean-only or allow the user to opt into another language. This is a natural-language policy concern because it imposes a specific language/locale without user choice or clear justification.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
Comments and all user-visible messages are written in Korean, including the completion output and required follow-up instructions. The policy forbids forcing a specific language without user opt-in unless the locale restriction is clearly documented and justified, which is not present here.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script persistently stores user-supplied task content, including the full raw input, title, owner, and due fields, into a JSONL log under the user's home directory without any notice, consent, minimization, or retention controls. This can expose sensitive personal or operational data entered into tasks and increases privacy and data-handling risk if the workspace is shared, backed up, or later accessed by other tools.

Vague Triggers

Low
Confidence
82% confidence
Finding
This markdown file defines `/todo <text>` as accepting arbitrary free text to create a task draft, but it does not provide negative examples or boundaries for what kinds of user messages should or should not be treated as task capture. That ambiguity can increase the chance of unintended activation or over-capture when users issue general-purpose text after the command.

Static analysis

No suspicious patterns detected.