Back to skill

Security audit

Natural Language Planner

Security checks for vulnerabilities and agentic risk

Overview

This planner is mostly coherent, but it can expose unauthenticated task data over LAN or public tunnels despite local-first privacy claims.

Install only if you are comfortable with this skill writing local task/project Markdown and running a dashboard. Keep the dashboard bound to localhost for normal use. Do not enable --network, public tunnels, static hosting, or systemd persistence for sensitive data unless you add authentication or put it behind a trusted access control layer, and review all sudo commands before running them.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/dashboard_server.py:48
Finding

Unauthenticated Disclosure of Planner Data over LAN and Public Tunnels

Content
View full analysis
None: """Route GET requests to the appropriate handler.""" parsed = urlparse(self.path) path = parsed.path if path.startswith("/api/"): self._handle_api(path, parsed.query) else: # Serve static files from the dashboard directory super().do_GET() def _handle_api(self, path: str, query_string: str) -> None: """Dispatch API requests.""" params = parse_qs(query_string) routes: dict[str, Any] = { "/api/stats": self._api_stats, "/api/projects": self._api_projects, "/api/tasks": self._api_tasks, "/api/search": self._api_search, "/api/due-soon": self._api_due_soon, "/api/overdue": self._api_overdue, "/api/health": self._api_health, } if path.startswith("/api/attachment/"): parts = path.split("/api/attachment/")[1].strip("/").split("/", 1) if len(parts) == 2: self._api_serve_attachment(unquote(parts[0]), unquote(parts[1])) else: self._json_response({"error": "Bad attachment path"}, status=400) return if path.startswith("/api/project/"): project_id = path.split("/api/project/")[1].strip("/") self._api_single_project(project_id) return if path.startswith("/api/task/"): task_id = path.split("/api/task/")[1].strip("/") self._api_single_task(task_id) return ``` ```python host = "0.0.0.0" if allow_network else "127.0.0.1" # ... _server = HTTPServer((host, actual_port), handler) ``` The same unauthenticated server can be made publicly reachable through the tunnel integration: ```python def _start_clo ...[truncated 2592 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
templates/dashboard/app.js:280
Finding

Stored HTML Attribute Injection through Unescaped Task Metadata

Content
View full analysis
tagHTML(t, task.project)) .join(""); const desc = task.description || ""; const deps = task.dependencies || []; const banner = buildBannerUrl(task); const pColor = getProjectColor(task.project); const borderStyle = pColor ? `style="border-left:3px solid ${esc(pColor)}"` : ""; return `
${banner ? `
` : ""}
${esc(task.title)}
${esc(task.status || "todo")}
${desc ? `
${esc(desc)}
` : ""}
${task.project ? `${esc(task.project)}` : ""} ${dueLabel ? `${isOverdue ? "Overdue: " : "Due "}${dueLabel}` : ""} ${tags}
${deps.length ? `
Depends on: ${deps.map(esc).jo ...[truncated 3551 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (63)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
93% confidence
Finding

Publishing a local planner dashboard to the internet materially increases attack surface and exposes potentially sensitive tasks, deadlines, attachments, and project notes. In this skill's context, remote access is not core to basic planning functionality, so bundling tunnel support is a risky capability amplification—especially when the README also notes the dashboard has no authentication.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The design principle stating data 'never leaves your machine' is contradicted by instructions for exposing the dashboard through tunnels. This is dangerous because users may rely on the privacy claim when deciding to store sensitive personal or business data, then unknowingly undermine that assumption through a documented feature.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Exposing a local service to the public internet and invoking external tunnel tooling are materially different from task capture and project organization. Users could unknowingly enable internet-reachable access to sensitive project content under a benign-sounding planner skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Exposing a local service to the public internet and invoking external tunnel tooling are materially different from task capture and project organization. Users could unknowingly enable internet-reachable access to sensitive project content under a benign-sounding planner skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Exposing a local service to the public internet and invoking external tunnel tooling are materially different from task capture and project organization. Users could unknowingly enable internet-reachable access to sensitive project content under a benign-sounding planner skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Exposing a local service to the public internet and invoking external tunnel tooling are materially different from task capture and project organization. Users could unknowingly enable internet-reachable access to sensitive project content under a benign-sounding planner skill.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 539)May include surrounding context.

md
| **Skill instructions** (`SKILL.md`) only | **No server action needed.** The SKILL.md is read by the AI agent, not by the running server. | The file is an agen

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

Including systemd service creation and management extends the skill from task planning into persistence and service administration. This is risky because it normalizes privileged operational changes and long-lived background execution that are not necessary for basic planner behavior.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
94% confidence
Finding

The instruction uses a placeholder-based sudo rm on /etc/systemd/system/<old-service>.service, which encourages destructive privileged deletion with a variable service name. If substituted incorrectly, it could remove the wrong unit file or normalize unsafe patterns for privileged file deletion.

Content

Scanner excerpt · SKILL.md (reported line 686)May include surrounding context.

bash
   sudo systemctl stop <old-service>
   sudo systemctl disable <old-service>
   sudo rm /etc/systemd/system/<old-service>.service
   sudo systemctl daemon-reload

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 708)May include surrounding context.

bash
sudo systemctl stop nlplanner-dashboard.service
sudo systemctl disable nlplanner-dashboard.service
sudo rm /etc/systemd/system/nlplanner-dashboard.service
sudo systemctl daemon-reload

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill metadata says it serves a local Kanban dashboard, but the CLI explicitly exposes a command to create remote public access to that dashboard. This creates a significant trust-boundary expansion: task/project data that users would reasonably expect to remain local can be made internet-accessible, and the code itself warns that the dashboard has no authentication.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The tunnel command starts the dashboard and then publishes it through a third-party tunneling service, producing a public URL for a dashboard that the code states has no authentication. In the context of a planner skill, this can expose sensitive personal or business tasks, project names, deadlines, and notes to anyone who obtains the link, making confidentiality loss the primary risk.

Content

No source excerpt is available for this finding.

Unvalidated Output Injection

High
Category
Output Handling
Confidence
90% confidence
Finding

Model output is used without validation or sanitization. Unvalidated output injected into downstream contexts (SQL, shell, HTML) enables injection attacks and arbitrary code execution.

Content

Scanner excerpt · templates/dashboard/app.js (reported line 577)May include surrounding context.

js
return;
    }

    els.searchResults.innerHTML = results.map(taskCardHTML).join("");
    attachCardClicks();
  }

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The architecture explicitly allows the dashboard to bind to 0.0.0.0, which exposes task and project data to other hosts on the network without any authentication. For a local task-management skill, this broadens the attack surface unnecessarily and can leak sensitive notes, deadlines, project metadata, and search results to anyone who can reach the port.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The security section states 'No data leaves the machine' while also documenting optional LAN exposure via 0.0.0.0, which is misleading and can cause operators to underestimate the risk of remote access. That mismatch increases the chance that users enable network binding without understanding that task data becomes available to other devices on the network.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Saying the AI will detect SKILL.md and activate the planner automatically suggests broad implicit enablement without clear user consent boundaries. In an agent environment, ambiguous auto-activation can lead to unintended task capture, filesystem writes, or side effects when ordinary conversation is misclassified as a planner request.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The guidance to 'just talk to your AI assistant' using ordinary project-related speech encourages very broad invocation semantics. In a natural-language agent system, this can cause accidental triggering from routine conversation, resulting in unintended task creation, data persistence, or related automations.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README makes a strong 'local-first' claim while also documenting a built-in tunneling feature that exposes the dashboard externally. This mismatch can mislead users into treating the skill as strictly local and cause them to expose sensitive task data without fully understanding the trust boundary change.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The example phrase for remote access overlaps with normal conversational language, making it plausible that a user casually discussing phone access could trigger a high-risk action. Because this action exposes a dashboard lacking authentication, accidental invocation has materially greater consequences than a benign local operation.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 126)May include surrounding context.

  1. Create the service file:
bash
sudo tee /etc/systemd/system/nlplanner-dashboard.service << 'EOF'
[Unit]
Description=Natural Language Planner Dashboard
After=network.target

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 149)May include surrounding context.

  1. Create the service file:
bash
sudo tee /etc/systemd/system/nlplanner-dashboard.service << 'EOF'
[Unit]
Description=Natural Language Planner Dashboard
After=network.target

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 150)May include surrounding context.

  1. Create the service file:
bash
sudo tee /etc/systemd/system/nlplanner-dashboard.service << 'EOF'
[Unit]
Description=Natural Language Planner Dashboard
After=network.target

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 151)May include surrounding context.

  1. Create the service file:
bash
sudo tee /etc/systemd/system/nlplanner-dashboard.service << 'EOF'
[Unit]
Description=Natural Language Planner Dashboard
After=network.target

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 162)May include surrounding context.

  1. Create the service file:
bash
sudo tee /etc/systemd/system/nlplanner-dashboard.service << 'EOF'
[Unit]
Description=Natural Language Planner Dashboard
After=network.target

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 642)May include surrounding context.

  1. Create the service file:
bash
sudo tee /etc/systemd/system/nlplanner-dashboard.service << 'EOF'
[Unit]
Description=Natural Language Planner Dashboard
After=network.target

Static analysis

No suspicious patterns detected.