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
msg_result = subprocess.run( [_OPENCLAW_BIN, "plan-tracker-deliver"], input=payload, text=True, capture_output=True, timeout=15, env={**os.e

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
auto_confirm

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
auto_confirm

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
PLIST

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
plist

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
PLIST

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
PLIST

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
mcp

VirusTotal

61/61 vendors flagged this plugin as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.