Back to plugin

Security audit

Plan Tracker

Security checks across malware telemetry and agentic risk

Overview

The skill matches its planning and reminder purpose, but installation can modify OpenClaw configuration and start persistent background services automatically.

Install only if you want a persistent reminder service on your machine. Review or run setup in dry-run mode first, expect changes to OpenClaw MCP configuration, and be aware that macOS uses launchd KeepAlive while other platforms use a watchdog daemon. Avoid the system-Python fallback, and enable email/webhook delivery only after reviewing what plan data will be sent and where.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (17)

Direct flow: os.environ.get (credential/environment) → subprocess.run (code execution)

High
Category
Data Flow
Content
})

        try:
            msg_result = subprocess.run(
                [_OPENCLAW_BIN, "plan-tracker-deliver"],
                input=payload, text=True, capture_output=True, timeout=15,
                env={**os.environ,
Confidence
80% confidence
Finding
The code forwards the full parent process environment into the openclaw subprocess, only prepending PATH. If this service runs with secrets or dangerous runtime variables set, an untrusted or compromised plugin/binary can read and exfiltrate them, expanding the blast radius beyond message delivery.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The skill does substantially more than expose plan-tracking tools: it automatically starts, restarts, and supervises a separate daemon process, including platform service integration via `launchctl`. In an MCP/agent context, this expands the runtime's authority and persistence characteristics beyond what a user would expect from a simple planning interface, creating a risky hidden capability boundary.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The docstring explicitly highlights that the daemon is owned by launchd so it does not inherit the MCP host's network sandbox, while the module also supports outbound notification channels such as email and webhooks. In context, this is a deliberate sandbox-bypass design that can let the skill regain network access outside the host's intended restrictions, materially increasing exfiltration and covert communication risk.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The file defines a privacy boundary via sanitize_plan() and explicitly documents that sensitive fields such as 'api_secret' must be masked before data is returned to AI context, but the storage accessors in this module return raw plan dictionaries. If callers rely on this module-level contract rather than independently sanitizing outputs, secrets can be exposed to the model or other downstream consumers, creating a data-leak vulnerability. In this skill context, that is especially relevant because plan data is intended to flow into AI context.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The script header says it is an installer for an OpenClaw plugin, but the actual behavior installs and configures the different 'plan-tracker' package and runs its setup flow. This mismatch can mislead reviewers and users into executing code they did not intend to trust, which is a supply-chain and social-engineering risk in an installer context.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README explicitly instructs users to run a setup command that modifies MCP configuration files and installs/starts a persistent daemon, but it does not present a clear warning about those system-level changes before execution. In an agent-skill context, silent config mutation and background service installation increase risk because users may execute the command expecting a normal local setup rather than persistent host modification.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
New plans are created with outbound notification channels enabled by default, including a webhook target and email API configuration fields. Even though the defaults point to localhost and email is disabled, this still normalizes automatic network-capable behavior in newly created objects and can lead to unintended data disclosure or SSRF-style misuse if other components later honor modified settings without explicit user consent or validation.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
When virtual environment creation fails, the script falls back to the system Python and uses pip with --break-system-packages to install dependencies and the plugin into the host environment. Modifying the system interpreter this way can overwrite or destabilize host packages and expands the blast radius from a plugin install to the entire machine, especially because the script does not require explicit user confirmation before doing so.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill advertises email sending through a third-party REST API but does not instruct the agent to warn users that plan data, reminder content, and recipient details may be transmitted to an external service. This creates a privacy and consent risk because users may enable email notifications without understanding that their data leaves the local/MCP environment.

Missing User Warnings

Medium
Confidence
81% confidence
Finding
The skill specifies automatic marking of a day as incomplete after a 10-minute timeout, but it does not require clear notice or confirmation that this automated data change will occur. This can silently alter user records and analytics, leading to inaccurate progress tracking and potentially coercive or misleading behavior in reminder workflows.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
plan = modify_plan_and_index(plan_name, _do_checkin)
    milestone = result_milestone[0]

    from plan_tracker.daily_tracker import auto_confirm_from_checkin
    auto_confirm_from_checkin(plan_name, progress_pct)

    return milestone
Confidence
82% confidence
Finding
After persisting a check-in, the function unconditionally invokes auto_confirm_from_checkin(plan_name, progress_pct), which performs an additional autonomous action based on user input without an explicit authorization, confirmation, or visible policy gate in this module. This creates a security-relevant trust boundary issue: a seemingly simple progress update can trigger further state changes elsewhere, increasing the risk of unintended or abused workflow manipulation if callers can submit crafted check-ins.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
milestone = result_milestone[0]

    from plan_tracker.daily_tracker import auto_confirm_from_checkin
    auto_confirm_from_checkin(plan_name, progress_pct)

    return milestone
Confidence
82% confidence
Finding
The imported auto_confirm_from_checkin function is executed immediately after a check-in is recorded, coupling a data-entry operation with an implicit follow-on decision. In this skill context, that makes the module more dangerous because the side effect is not obvious from the public API contract and may permit users to influence confirmations or daily tracking state indirectly through progress values.

Session Persistence

Medium
Category
Rogue Agent
Content
# Lock file to prevent concurrent daemon starts
_DAEMON_LOCK_FILE = DATA_DIR / "daemon.lock"
_DAEMON_LAUNCHD_LABEL = "com.plan-tracker.daemon"
_DAEMON_LAUNCHD_PLIST = (
    Path.home() / "Library" / "LaunchAgents" / f"{_DAEMON_LAUNCHD_LABEL}.plist"
)
Confidence
84% confidence
Finding
Referencing a LaunchAgent plist under the user's `~/Library/LaunchAgents` indicates use of OS-level persistence for the daemon. In context with the auto-start/watchdog logic, this means the skill is designed to survive beyond the MCP session, which is a risky persistence mechanism for an agent-facing tool and can outlive user expectations or host controls.

Session Persistence

Medium
Category
Rogue Agent
Content
_DAEMON_LOCK_FILE = DATA_DIR / "daemon.lock"
_DAEMON_LAUNCHD_LABEL = "com.plan-tracker.daemon"
_DAEMON_LAUNCHD_PLIST = (
    Path.home() / "Library" / "LaunchAgents" / f"{_DAEMON_LAUNCHD_LABEL}.plist"
)
Confidence
84% confidence
Finding
The explicit construction of a LaunchAgent plist path is part of a persistence mechanism, not merely a transient runtime helper. Within an agent skill, this broadens execution beyond the active session and can maintain a long-lived component with network-capable reminder features.

Session Persistence

Medium
Category
Rogue Agent
Content
def _start_daemon_via_launchd() -> bool:
    """Start the installed daemon service without inheriting the MCP sandbox."""
    if not _DAEMON_LAUNCHD_PLIST.is_file():
        logger.error(
            "Daemon LaunchAgent is not installed; run `python -m plan_tracker.cli setup`"
        )
Confidence
86% confidence
Finding
The function documentation states the daemon service is started without inheriting the MCP sandbox, reinforcing that persistence is paired with sandbox escape characteristics. That combination increases the danger of long-lived execution with capabilities different from the original host session.

Session Persistence

Medium
Category
Rogue Agent
Content
if probe.returncode == 0:
            action = ["launchctl", "kickstart", target]
        else:
            action = ["launchctl", "bootstrap", domain, str(_DAEMON_LAUNCHD_PLIST)]
        result = subprocess.run(
            action,
            stdout=subprocess.DEVNULL,
Confidence
87% confidence
Finding
Using `launchctl bootstrap` with a user LaunchAgent plist is an explicit activation of persistent user-level execution. Combined with the watchdog and notification features, this gives the skill durable background presence that is more dangerous than normal plan-tracking state storage and can continue operating independently of the session.

Known Vulnerable Dependency: mcp — 9 advisory(ies): CVE-2025-53366 (MCP Python SDK vulnerability in the FastMCP Server causes validation error, lead); CVE-2025-66416 (Model Context Protocol (MCP) Python SDK does not enable DNS rebinding protection); CVE-2026-52870 (MCP Python SDK: Experimental task handlers allow any client to access and cancel) +6 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
The project declares an unconstrained dependency on `mcp>=1.0.0`, and the static analysis indicates multiple known advisories affecting the MCP Python SDK. Because the version range permits installation of vulnerable releases, consumers may resolve to a version exposed to issues such as validation flaws, DNS rebinding, or unauthorized task access depending on deployment and enabled features.

VirusTotal

61/61 vendors flagged this plugin as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.