Back to skill

Security audit

Task Engine

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent task orchestrator, but it needs review because it can operate outside its task storage path and includes an unsafe instruction to delete the live task directory during testing.

Install only after reviewing and fixing path validation for task_id and subtask_id, removing the rm -rf live-directory test command, and configuring Discord IDs for your own workspace. Treat task descriptions and prior agent outputs as untrusted before dispatching them to other agents, and review/redact Discord-formatted messages before posting them externally.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/engine/task_store.py:33
Finding

Path Traversal Through Unvalidated Task and Subtask Identifiers

Content
View full analysis

Vulnerability Details

File Location: scripts/engine/task_store.py:33-35, 68-74, 199-208, 317-329, 353-366; input entry points in scripts/task_engine.py:788-789, 826-827, 840-841
Vulnerability Type: Path traversal and unrestricted filesystem access
Risk Level: High

Vulnerable Code

python
def get_task_dir(task_id: str) -> Path:
    return get_tasks_dir() / task_id
python
@contextmanager
def task_lock(task_id: str):
    """Per-task file lock. Uses fcntl on Unix, msvcrt on Windows."""
    lock_dir = get_tasks_dir() / ".locks"
    lock_dir.mkdir(parents=True, exist_ok=True)
    lock_path = lock_dir / f"{task_id}.lock"

    fd = open(lock_path, "w")
python
def read_task(task_id: str) -> Optional[Task]:
    """Read a task from its task.json."""
    task_dir = get_task_dir(task_id)
    task_path = task_dir / "task.json"
    if not task_path.exists():
        # Check archive
        archive_path = get_archive_dir() / task_id / "task.json"
        if archive_path.exists():
            data = json.loads(archive_path.read_text(encoding="utf-8"))
            return Task.from_dict(data)
        return None
    data = json.loads(task_path.read_text(encoding="utf-8"))
    return Task.from_dict(data)
python
def read_subtask(task_id: str, subtask_id: str) -> Optional[Subtask]:
    """Read a subtask JSON."""
    task_dir = get_task_dir(task_id)
    path = task_dir / f"{subtask_id}.json"
    if not path.exists():
        return None
    data = json.loads(path.read_text(encoding="utf-8"))
    return Subtask.from_dict(data)


def save_subtask(subtask: Subtask):
    """Save subtask JSON atomically."""
    task_dir = get_task_dir(subtask.parent_task)
    atomic_write(task_dir / f"{subtask.id}.json", subtask.to_dict())
python
def archive_task(task_id: str) -> bool:
    """Move a terminal-state task to archive/."""
    task = read_task(task_id)
    if task is None:
        logger.error("Task %s not found", task_id)
        retu
...[truncated 3587 chars]
Remediation
View remediation

Remediation Suggestions

  1. Validate identifiers at every trust boundary.

    • Require task IDs to match a strict expression such as ^TASK-[0-9]{3,}$.
    • Require subtask IDs to match a strict expression such as ^subtask_[0-9]{2,}$.
    • Reject absolute paths, path separators, empty values, . and ...
  2. Enforce canonical path containment. Resolve the base and candidate paths before access and verify containment:

    python
    def safe_child(base: Path, component: str) -> Path:
        if not component or Path(component).is_absolute():
            raise ValueError("Invalid path component")
        base = base.resolve()
        candidate = (base / component).resolve()
        if not candidate.is_relative_to(base):
            raise ValueError("Path escapes the permitted directory")
        return candidate
    

    Apply equivalent checks to task directories, archive destinations, lock files, log files, task files, and subtask files.

  3. Validate persisted identifiers. Treat IDs loaded from task.json, subtask_*.json, and index.json as untrusted. Validate them before using them to build paths or save objects.

  4. Harden archive operations. Confirm both source and destination remain under their expected canonical roots. Reject an existing destination and avoid following unexpected symbolic links.

  5. Harden write operations. Create temporary files securely in the verified destination directory, use unique temporary names, and reject symbolic-link targets where supported.

  6. Add regression tests. Cover traversal and absolute-path attempts against status, transition, dispatch, subtask, check, archive, task locking, logging, and index rebuilding. Verify that no file is read, created, modified, or moved outside the temporary task root.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (20)

Self-Modification

High
Category
Rogue Agent
Confidence
95% confidence
Finding

The skill explicitly instructs modification of SKILL.md, which is the skill's own definition/instruction surface. Self-modification is dangerous because it can alter future agent behavior, expand privileges, or persist unsafe instructions in a place later executions may trust. In a skill file, this is more sensitive than ordinary documentation edits because SKILL.md may be consumed as executable guidance by the agent framework.

Content

Scanner excerpt · CLAUDE.md (reported line 159)May include surrounding context.

md
- rebuild-index recovery
- Error cases return non-zero exit code

### 6. Update SKILL.md

Enhance the existing SKILL.md with:
- Auto-dispatch section with examples

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This finding is a specific instance of path-targeted destructive deletion: rm -rf /home/zeron/.openclaw/workspace/tasks. The danger is concrete and not hypothetical—the command removes the live runtime tasks directory identified earlier in the skill metadata, so exploitation would wipe orchestration records, progress tracking, and recovery data. The surrounding context makes it more dangerous because the same document labels that path as the active runtime location.

Content

Scanner excerpt · CLAUDE.md (reported line 186)May include surrounding context.

md
python3 -m pytest tests/ -v

# Also run the end-to-end manual test:
rm -rf /home/zeron/.openclaw/workspace/tasks
python3 scripts/task_engine.py create "E2E test" --priority P1 --json
python3 scripts/task_engine.py transition TASK-001 approve --json
python3 scripts/task_engine.py dispatch TASK-001 "Dev work" --agent claude-code --type dev --json

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This finding is a specific instance of path-targeted destructive deletion: rm -rf /home/zeron/.openclaw/workspace/tasks. The danger is concrete and not hypothetical—the command removes the live runtime tasks directory identified earlier in the skill metadata, so exploitation would wipe orchestration records, progress tracking, and recovery data. The surrounding context makes it more dangerous because the same document labels that path as the active runtime location.

Content

Scanner excerpt · CLAUDE.md (reported line 186)May include surrounding context.

md
python3 -m pytest tests/ -v

# Also run the end-to-end manual test:
rm -rf /home/zeron/.openclaw/workspace/tasks
python3 scripts/task_engine.py create "E2E test" --priority P1 --json
python3 scripts/task_engine.py transition TASK-001 approve --json
python3 scripts/task_engine.py dispatch TASK-001 "Dev work" --agent claude-code --type dev --json

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · DESIGN.md (reported line 799)May include surrounding context.

md
"description": "Create User model with email/password, JWT token generation (access + refresh), bcrypt password hashing utility.",
  "acceptance_criteria": [
    "User model with email, hashed_password, created_at fields",
    "JWT access token (15 min) and refresh token (7 day) generation",
    "Password hash/verify functions using bcrypt",
    "Unit tests for all utilities"
  ],

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The skill markets itself broadly as an orchestration engine, but the documented behavior includes concrete persistent storage operations on task data and index/archive structures without prominently disclosing those write-side effects in the top-level description. In practice, users may invoke it expecting monitoring/reporting and instead cause durable state changes across the workspace.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill markets itself broadly as an orchestration engine, but the documented behavior includes concrete persistent storage operations on task data and index/archive structures without prominently disclosing those write-side effects in the top-level description. In practice, users may invoke it expecting monitoring/reporting and instead cause durable state changes across the workspace.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill markets itself broadly as an orchestration engine, but the documented behavior includes concrete persistent storage operations on task data and index/archive structures without prominently disclosing those write-side effects in the top-level description. In practice, users may invoke it expecting monitoring/reporting and instead cause durable state changes across the workspace.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_cli.py (reported line 17)May include surrounding context.

python
def run_cli(*args, expect_fail=False):
    """Run task_engine.py with args. Returns (returncode, stdout, stderr)."""
    env = os.environ.copy()
    if _cli_tasks_dir:
        env["TASK_ENGINE_TASKS_DIR"] = str(_cli_tasks_dir)
    cmd = [sys.executable, SCRIPT] + list(args)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The design explicitly sends task and subtask status to Discord and performs periodic scans of task data, but it does not include any privacy notice, data classification rules, or constraints on what may be posted externally. In a multi-agent orchestration system, task descriptions, progress notes, file paths, blockers, and human mentions may contain sensitive project, operational, or personal data, so silent forwarding to Discord creates a real data-exposure risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The document instructs use of a Discord bot token via environment variables but provides no handling guidance for secret storage, rotation, masking, or logging exclusions. While environment variables are common, omitting credential-safety requirements in a design that integrates messaging and automation increases the chance of accidental token leakage through config files, logs, crash output, or agent-visible context.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill exposes shell execution and persistent file read/write behavior but does not declare any tool scope or allowed-tools boundaries. In an agent environment, this weakens least-privilege controls and can let the skill perform broader filesystem or command actions than a user would reasonably infer from metadata alone.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill generates Discord-formatted status and alert messages about active tasks, but the description does not warn that project names, progress, blockers, and completion details may be exposed through notifications or copied into chat systems. In environments with sensitive project metadata, that omission raises data leakage risk even if the module only formats strings locally.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The top-level documentation explicitly describes this module as pure formatting with no side effects or API calls. In practice, the module reads config/settings.yaml during formatting-related operations and format_heartbeat_digest imports and calls storage accessors to load tasks and subtasks, which contradicts the stated 'pure formatting' behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

Given the skill context and this file's role as a Discord formatter, the expected responsibility is message rendering from supplied data. format_heartbeat_digest goes beyond formatting by fetching task details and subtasks from persistent storage, introducing data-access capability that is not obviously required for a formatter component.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The dispatcher builds agent prompts by embedding dependency titles, descriptions, and prior result summaries directly into natural-language prompt text without any trust boundary or delimiting. Because those fields come from task/subtask data and previous agent outputs, an attacker can plant prompt-injection content that manipulates the downstream agent, causes disclosure of prior outputs, or alters execution behavior in a multi-agent workflow.

Content

No source excerpt is available for this finding.

Ssd 1

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The generated dispatch prompt presents user-controlled subtask title, description, acceptance criteria, constraints, and dependency text as the agent's operative instructions. In a task-orchestration engine that dispatches work to other agents and tells them to run an OpenClaw command on completion, this creates a direct prompt-injection channel that can redirect the agent, exfiltrate workspace or prior-task data, or induce unintended tool use.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% 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.

Content

Scanner excerpt · scripts/engine/task_store.py (reported line 133)May include surrounding context.

python
def add_to_index(task: Task):
    """Add a task to index.json."""
    index = read_index()
    entry = IndexEntry.from_task(task)
    index["tasks"].append(entry.to_dict())

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 · tests/test_cli.py (reported line 21)May include surrounding context.

python
if _cli_tasks_dir:
        env["TASK_ENGINE_TASKS_DIR"] = str(_cli_tasks_dir)
    cmd = [sys.executable, SCRIPT] + list(args)
    result = subprocess.run(cmd, capture_output=True, text=True, env=env, timeout=30)
    if not expect_fail and result.returncode != 0:
        print(f"STDOUT: {result.stdout}")
        print(f"STDERR: {result.stderr}")

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill generates Discord-formatted status and alert messages about active tasks, but the description does not warn that project names, progress, blockers, and completion details may be exposed through notifications or copied into chat systems. In environments with sensitive project metadata, that omission raises data leakage risk even if the module only formats strings locally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code performs persistent file-modifying operations by saving subtasks, saving tasks, updating index entries, and appending logs during routine checks. While the module docstring says it 'scans' and 'returns alerts', it does not clearly disclose that running the checker also mutates task state and writes heartbeat history/log data.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.destructive_delete_command

Documentation contains a destructive delete command without an explicit confirmation gate.

Warn
Code
suspicious.destructive_delete_command
Location
CLAUDE.md:186