Back to skill

Security audit

Live Task Pulse

Security checks for vulnerabilities and agentic risk

Overview

This task-tracking skill has a coherent purpose, but it automatically pushes task details to chat, persists and deletes local task records, and contains an unsafe task-file access bug.

Install only if you want automatic progress tracking and chat notifications, and avoid including secrets, credentials, private file contents, or sensitive error details in task names or messages. Do not add the HEARTBEAT.md cleanup rule unless you understand which task directory it will delete from. The task-ID path handling should be fixed before use in shared or sensitive environments.

Vulnerability Patterns
  • 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
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:3
Finding
Automatic Agent Activation and Unsolicited Message-Tool Use<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:3`, `SKILL.md:31-67` **Vulnerability Type**: Agent instruction hijacking **Risk Level**: High ### Vulnerable Code Snippet ```yaml description: Real-time task progress tracking with live push notifications. MANDATORY for ALL multi-step tasks (>30s or >2 tool calls). Activate automatically — do not wait for user to request it. Unique dual-layer architecture — file persistence for crash recovery + message tool push for real-time updates. Features step-based progress, stall detection (3min), auto-cleanup, and a Python CLI. Also triggers when user asks "what's running" / "task status" / "任务进度". ``` ```markdown ### Create task → push start notification ```bash TASK_ID=$(python3 scripts/task_pulse.py create "任务名" "步骤1" "步骤2" "步骤3") ``` Then immediately call `message` tool: ``` message(action="send", message="🚀 开始【任务名】\n📋 步骤1 → 步骤2 → 步骤3\n🔄 当前: 步骤1") ``` ### Advance to next step → push progress ```bash python3 scripts/task_pulse.py next "$TASK_ID" "抓取了25条数据" ``` Then push: `message(action="send", message="✅ [1/3] 步骤1完成(抓取了25条数据)\n🔄 → 步骤2")` ``` The mandatory rules additionally state: ```markdown 1. **Always push after file update** — file update alone is invisible to users 2. **Push format**: emoji + `[done/total]` + current step + one-line info (≤3 lines) 3. **Push frequency**: every step transition; long steps max once per 30s ``` ### Technical Analysis The skill declares itself mandatory for every multi-step or sufficiently long task and explicitly tells the agent to activate it without waiting for a user request. It then requires repeated use of the `message` tool after local state updates. These instructions alter the behavior of the agent across otherwise unrelated tasks. Task names, individual steps, progress messages, errors, and results can contain operational or sensitive information. Automatically forwarding this content to the active messaging channel exceeds the behavior needed for ...[truncated 1494 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the statements that activation is mandatory and automatic. 2. Require explicit user opt-in before enabling progress tracking for a task. 3. Separate local persistence from external notifications and allow each capability to be enabled independently. 4. Obtain explicit approval before the first `message` tool call, clearly identifying the destination and the information that will be sent. 5. Do not include secrets, credentials, private file contents, or sensitive error details in notifications. 6. Add configurable redaction and message-preview controls. 7. Make notification frequency user-configurable rather than enforcing a global push after every state change. 8. Document that the active message channel may be visible to participants other than the initiating user. ]]>

T02 · Agent Memory Poisoning

Warning
Location
references/integration-guide.md:22
Finding
Persistent Modification of Agent Heartbeat Instructions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:79`, `references/integration-guide.md:22-25` **Vulnerability Type**: Persistent agent-state modification **Risk Level**: Medium ### Vulnerable Code Snippet ```markdown - **Heartbeat cleanup**: Add `python3 scripts/task_pulse.py cleanup` to HEARTBEAT.md ``` The integration guide gives a persistent configuration instruction: ```markdown ## Heartbeat Cleanup Add to HEARTBEAT.md: ``` - Run task cleanup: python3 ~/.openclaw/workspace/skills/live-task-pulse/scripts/task_pulse.py cleanup ``` ``` ### Technical Analysis The documentation directs modification of `HEARTBEAT.md`, which is persistent agent configuration rather than temporary state for the current invocation. Once added, the instruction can affect future sessions and cause recurring execution of the cleanup command. The cleanup operation scans the configured task directory and deletes JSON records whose status is `done` or `error` and whose completion timestamp is older than the configured retention period. Although this is presented as maintenance behavior, placing it in persistent heartbeat instructions extends the skill’s influence beyond the original run. This finding is classified as agent memory poisoning because the skill asks for a new rule to be written into persistent agent instructions. The reviewed files do not automatically edit `HEARTBEAT.md`; exploitation depends on the agent or user following the documented instruction. ### Attack Path 1. The skill or integration guide is loaded. 2. The agent follows the instruction to add the cleanup command to `HEARTBEAT.md`. 3. The new instruction persists after the current task or session ends. 4. During later heartbeat cycles, the agent executes `task_pulse.py cleanup`. 5. The script scans the shared task directory. 6. Completed or failed task records older than the retention threshold are deleted without a new approval for each cleanup run. ### Impact Assessment The persistent r ...[truncated 476 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Present heartbeat integration only as an optional administrative action. 2. Require explicit user approval before modifying `HEARTBEAT.md` or any other persistent agent configuration. 3. Do not instruct the agent to make persistent changes automatically. 4. Show the exact deletion scope, retention period, and task directory before installation. 5. Provide clear instructions for removing or disabling the heartbeat rule. 6. Prefer an external scheduler configured by an administrator instead of persistent agent-memory instructions. 7. Add a dry-run cleanup mode that lists candidate files without deleting them. 8. Consider per-agent directories or ownership metadata so one agent cannot clean another agent’s task records. 9. Require confirmation before deletion when the task directory is shared. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/task_pulse.py:43
Finding
Task Identifier Path Traversal Allows Out-of-Directory JSON Access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/task_pulse.py:43-66` **Vulnerability Type**: Path traversal and unsafe file access **Risk Level**: High ### Vulnerable Code Snippet ```python def task_path(task_id): return TASK_DIR / f"{task_id}.json" def find_task(task_id): """Find task file by exact match or prefix.""" p = task_path(task_id) if p.exists(): return p for f in sorted(TASK_DIR.glob("*.json")): if f.stem.startswith(task_id): return f return None def load_task(task_id): p = find_task(task_id) if not p: print(f"Error: task '{task_id}' not found", file=sys.stderr) sys.exit(1) with open(p) as f: return json.load(f), p def save_task(data, path): data["updatedAt"] = now_iso() path.parent.mkdir(parents=True, exist_ok=True) with open(path, "w") as f: json.dump(data, f, ensure_ascii=False, indent=2) ``` ### Technical Analysis The commands `next`, `heartbeat`, `done`, `error`, and `status` accept a caller-controlled task identifier. `task_path()` concatenates that identifier with the `.json` suffix and joins it to `TASK_DIR`, but it does not reject path separators, `..` components, absolute paths, or symlink-based escapes. `find_task()` checks whether the resulting path exists and returns it without resolving the path or verifying that it remains beneath the configured task directory. `load_task()` subsequently opens and parses that file as JSON. The `status` command prints the parsed object, while mutating commands pass the same path to `save_task()`, which overwrites the selected file. An attacker able to invoke the CLI can therefore use traversal components to reference an existing JSON file outside `TASK_DIR`. The `.json` suffix limits direct targets to paths that resolve with that suffix, and mutating operations generally require content compatible with the expected task structure. These constraints reduce but do not elimi ...[truncated 1845 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate every externally supplied task identifier against a strict allowlist, such as: ```python TASK_ID_RE = re.compile(r"^[A-Za-z0-9_-]{1,128}$") def validate_task_id(task_id): if not TASK_ID_RE.fullmatch(task_id): raise ValueError("Invalid task identifier") ``` 2. Reject absolute paths, path separators, `.` and `..` components, null bytes, and platform-specific separator variants. 3. Resolve both the task directory and candidate path, then enforce containment: ```python base = TASK_DIR.resolve() candidate = (base / f"{task_id}.json").resolve() if candidate.parent != base: raise ValueError("Task path escapes task directory") ``` 4. Reject symlink task files or open files using platform-supported no-follow semantics where available. 5. Avoid ambiguous prefix matching. Require exact generated task IDs, or fail when a prefix matches more than one record. 6. Use atomic writes through a securely created temporary file in the same validated directory, followed by `os.replace()`. 7. Create the task directory and files with restrictive permissions. 8. Add regression tests covering `../`, absolute paths, nested separators, symlink escapes, empty identifiers, and ambiguous prefixes. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • 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 (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The skill claims mandatory live push notifications, automatic activation, status-trigger behavior, and a dual-layer architecture, but the content only documents manual CLI commands and suggested message calls. This mismatch is dangerous because operators may rely on progress visibility, notification, or recovery guarantees that are not actually enforced, causing silent failures, missed status reporting, or unsafe assumptions about task monitoring.

Vague Triggers

High
Confidence
94% confidence
Finding
Triggering on broad phrases like 'what's running', 'task status', or '任务进度' without stronger scoping can cause unintended invocation during normal conversation. In a shared or multi-context environment, this may surface or modify task-tracking state for the wrong workflow, confusing users and potentially exposing metadata about active work.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The manifest describes live push notifications via a message tool plus file persistence for crash recovery, but this script implements only a local CLI that reads and writes task JSON files and prints to stdout. There is no code for any messaging/push channel, so a central claimed behavior of the skill is absent from the implementation.

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill describes behavior that relies on writing JSON state to disk and potentially interacting with execution tooling, but it does not declare any explicit tool scope or permissions boundaries. That creates an authorization ambiguity where a host may allow broader capabilities than users or reviewers expect, increasing the risk of unintended file persistence or access to environment-backed execution context.

Vague Triggers

Medium
Confidence
89% confidence
Finding
Triggering on broad phrases like 'what's running', 'task status', or '任务进度' without stronger scoping can cause unintended invocation during normal conversation. In a shared or multi-context environment, this may surface or modify task-tracking state for the wrong workflow, confusing users and potentially exposing metadata about active work.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill promotes persistent JSON storage and live message pushes, but it does not provide an explicit warning or consent model for storing task details or sending outbound notifications. Task names, progress notes, links, and errors can contain sensitive business or personal information, so silent persistence and broadcasting increase privacy and data leakage risk.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The examples and prescribed push formats hard-code Chinese notification text such as '开始', '当前', '失败', and '登录过期' without indicating that language should match the user's preference. This creates a language policy concern because the skill appears to enforce a specific locale rather than offering a choice.

Session Persistence

Medium
Category
Rogue Agent
Content
```
# In cron task message:
1. python3 task_pulse.py create "日报发布" "抓取" "筛选" "写稿" "封面" "发布" "通知"
2. After each step: task_pulse.py next + message push
3. On success: task_pulse.py done + message push  
4. On failure: task_pulse.py error + message push
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The message templates in the Start, Progress, Complete, Error, and Stall Alert sections are written exclusively in Chinese. The policy requires avoiding forced language or locale choices unless the skill offers opt-in or clearly documents a justified regional constraint, which this file does not do.

Session Persistence

Medium
Category
Rogue Agent
Content
Live Task Pulse — CLI for real-time task tracking.

Usage:
  task_pulse.py create <name> <step1> [step2] ...   → prints taskId
  task_pulse.py next <taskId> [message]              → advance step
  task_pulse.py heartbeat <taskId> [message]         → update current step
  task_pulse.py done <taskId> [result]               → mark complete
Confidence
66% confidence
Finding
This tool persists task names, step descriptions, status messages, results, and errors as JSON under a user-home directory by default, creating durable local records of potentially sensitive workflow content. In an agent context, these fields can easily contain secrets, internal filenames, investigation details, or user data, so persistence increases exposure to local users, backups, and forensic recovery if file permissions or retention are not tightly controlled.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
This code file performs irreversible file deletion via the cleanup command, but the only disclosure is a brief usage line saying it will 'remove old completed tasks'. There is no confirmation prompt and no stronger user-facing warning near the deletion logic or command implementation to highlight that task JSON files will be permanently deleted.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The description says the skill is mandatory for long or multi-tool tasks and should activate automatically, including when users ask for running-task status. This file exposes only manual subcommands invoked via CLI arguments and contains no logic for detecting task duration/tool-call thresholds or natural-language trigger handling.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Several user-visible status messages are hard-coded in Chinese, such as completion, no-task, running-state, error, and cleanup outputs. This imposes a specific language/locale on all users without opt-in or documented justification, which matches the language-policy violation criteria.

Static analysis

No suspicious patterns detected.