Back to skill

Security audit

4to1 Planner

Security checks for vulnerabilities and agentic risk

Overview

This planning skill has a coherent purpose, but it stores cloud API tokens unsafely and ships shell scripts that can execute config-file contents as code.

Review before installing. Use the local backend or tightly scoped integrations where possible, avoid putting sensitive goals or reflections into connected services unless intended, and do not run the bundled status script against a config file you do not fully trust. The publisher should replace sourced shell config with inert parsing and store tokens with secure permissions or a secret manager.

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/setup.sh:33
Finding

Command Injection Through Executable Configuration File

Content
View full analysis
> "$CONFIG_DIR/config" read -p "Paste the parent page ID: " parent_page echo "NOTION_PARENT_PAGE=$parent_page" >> "$CONFIG_DIR/config" read -p "Paste your Todoist API token: " todoist_key echo "TODOIST_API_KEY=$todoist_key" >> "$CONFIG_DIR/config" ``` `scripts/status.sh:12` subsequently executes the configuration file in the current shell: ```bash source "$CONFIG" ``` ### Technical Analysis The setup script treats API credentials and page identifiers as data but serializes them as unquoted shell expressions. The status script then uses `source`, which treats every line in the file as executable shell code. Shell metacharacters and command substitutions contained in a supplied value are written literally to the configuration file. When the file is later sourced, those expressions are evaluated. For example, a token entered as: ```bash $(malicious_command) ``` can produce a configuration entry such as: ```bash TODOIST_API_KEY=$(malicious_command) ``` The command executes when `status.sh` sources the file. An attacker who can modify `~/.config/4to1/config` can also insert arbitrary shell statements directly. Configuration parsing does not require code execution. This behavior exceeds the minimum privileges needed to read backend settings and test API connectivity. ### Attack Path 1. An attacker convinces the user to enter a crafted API token or Notion page identifier during setup, or gains write access to `~/.config/4to1/config`. 2. `scripts/setup.sh` stores the attacker-controlled value as unquoted shell synt ...[truncated 866 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup.sh:5
Finding

API Credentials Stored Without Enforced Restrictive Permissions

Content
View full analysis
> "$CONFIG_DIR/config" ``` ```bash read -p "Paste your Todoist API token: " todoist_key echo "TODOIST_API_KEY=$todoist_key" >> "$CONFIG_DIR/config" ``` ### Technical Analysis The script does not establish a restrictive `umask`, create the directory with mode `700`, or enforce mode `600` on the credential file. The resulting permissions depend on the caller's environment. Under a common `umask` of `022`, a newly created directory may be mode `755` and a newly created file may be mode `644`, making the credentials readable by other local users. The use of `read -p` also leaves secret input visible on the terminal while it is entered. This can expose credentials through shoulder surfing, screen recording, terminal sharing, or captured session output. Plaintext storage may be necessary for unattended API access, but unrestricted filesystem permissions and visible input are not necessary for the Skill's planning functionality. ### Attack Path 1. A user runs `scripts/setup.sh` and supplies a valid Notion or Todoist bearer token. 2. The script writes the token to `~/.config/4to1/config`. 3. The surrounding environment has a permissive `umask`, or the file already has permissive permissions. 4. Another local user or process reads the configuration file. 5. The attacker reuses the bearer token against the relevant service API. 6. The attacker gains access to the data and operations a ...[truncated 721 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (38)

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/status.sh (reported line 21)May include surrounding context.

sh
case $BACKEND in
  notion)
    echo "Testing Notion connection..."
    RESULT=$(curl -s -o /dev/null -w "%{http_code}" \
      "https://api.notion.com/v1/users/me" \
      -H "Authorization: Bearer $NOTION_API_KEY" \
      -H "Notion-Version: 2025-09-03")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README advertises that the AI can connect to Notion, Todoist, and Google Calendar and 'reads your Notion/Todoist and knows where you stand,' but it does not provide any privacy, scope, retention, or consent warning. This can mislead users about the extent of data access and creates a risk of over-collection or unexpected exposure of sensitive planning data, calendar contents, and personal goals. Because this is a personal planning skill, the connected data is likely to be highly sensitive and contextual.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README instructs users to invoke the skill with a very generic phrase ('Help me set up my 4to1 planning system'). In an agent ecosystem, broad and natural-language trigger phrases can cause accidental invocation during ordinary planning conversations, which may lead the skill to request or use connected integrations without the user explicitly intending to engage this specific skill. The planning context increases risk because requests like setup, weekly review, or focus advice are common assistant interactions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill advertises shell-capable behavior but does not declare any explicit tool scope or permission boundaries. That creates a confused-deputy risk where a broadly invocable planning skill could run filesystem or network-affecting commands without clear least-privilege constraints or user understanding.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The activation phrases are extremely broad and overlap with ordinary planning requests such as weekly reviews or daily focus. This increases the chance the skill will trigger unexpectedly and begin reading/writing local files or external planning systems in contexts where the user did not intend to invoke this specific skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs storing and syncing sensitive personal planning data to Notion, Todoist, Google, and local files without a prominent user-facing disclosure about what data leaves the session, where it is stored, and how long it persists. Because the collected content includes long-term goals, habits, blockers, and daily tasks, unintended disclosure can reveal highly sensitive personal or business information.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

The skill instructs users to persist API keys in plaintext under ~/.config/4to1/config. Plaintext credential storage materially increases the risk of token theft by other local processes, backups, or accidental disclosure, enabling unauthorized access to the user's Notion or Todoist data.

Content

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

Option 1: Notion (Recommended)

bash
# 1. Create a Notion integration at https://www.notion.so/my-integrations
# 2. Copy the API key (starts with ntn_)
# 3. Store it:
mkdir -p ~/.config/4to1

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

The workflow persists identifiers and created resources across sessions and relies on locally stored auth material to keep modifying remote data later. Persistence is expected for a planner, but without explicit consent and secure secret handling it creates a durable attack surface and privacy risk.

Content

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

md
NOTION_KEY=$(grep NOTION_API_KEY ~/.config/4to1/config | cut -d= -f2)
PARENT_PAGE=$(grep NOTION_PARENT_PAGE ~/.config/4to1/config | cut -d= -f2)

# Create the 4To1 Planning Hub page
curl -s -X POST "https://api.notion.com/v1/pages" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This command transmits user planning content and identifiers to the Notion API over the network. In context the transmission is intentional functionality, but it is still security-relevant because it can export sensitive personal data to a third party and depends on a bearer token stored locally.

Content

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

md
PARENT_PAGE=$(grep NOTION_PARENT_PAGE ~/.config/4to1/config | cut -d= -f2)

# Create the 4To1 Planning Hub page
curl -s -X POST "https://api.notion.com/v1/pages" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This command transmits user planning content and identifiers to the Notion API over the network. In context the transmission is intentional functionality, but it is still security-relevant because it can export sensitive personal data to a third party and depends on a bearer token stored locally.

Content

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

md
PARENT_PAGE=$(grep NOTION_PARENT_PAGE ~/.config/4to1/config | cut -d= -f2)

# Create the 4To1 Planning Hub page
curl -s -X POST "https://api.notion.com/v1/pages" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

Creating a Notion database sends structured planning schema and future user content to a third-party service. In this skill, the danger is less about code execution and more about silent persistence and remote storage of sensitive planning information.

Content

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

md
}"

# Create Projects database (tracks items across all 4 layers)
curl -s -X POST "https://api.notion.com/v1/databases" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This creates a Sprint Log database in Notion and establishes persistent remote storage for reflections, completion rates, and energy levels. Those fields can contain sensitive behavioral and productivity data that should not be transmitted without clear informed consent.

Content

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

md
}"

# Create Sprint Log database (2-week tracking cycles)
curl -s -X POST "https://api.notion.com/v1/databases" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This sends project names and account-authenticated requests to Todoist using a bearer token. Although expected for the feature, it still creates an external data exposure path and can modify a user's remote task structure if invoked unexpectedly.

Content

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

md
TODOIST_KEY=$(grep TODOIST_API_KEY ~/.config/4to1/config | cut -d= -f2)

for project in "🔭 4-Year Vision" "📊 3-Month Milestones" "🏃 2-Week Sprint" "✅ Daily Tasks" "🚫 Not-To-Do"; do
  curl -s -X POST "https://api.todoist.com/rest/v2/projects" \
    -H "Authorization: Bearer $TODOIST_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"name\": \"$project\"}"

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This sends project names and account-authenticated requests to Todoist using a bearer token. Although expected for the feature, it still creates an external data exposure path and can modify a user's remote task structure if invoked unexpectedly.

Content

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

md
TODOIST_KEY=$(grep TODOIST_API_KEY ~/.config/4to1/config | cut -d= -f2)

for project in "🔭 4-Year Vision" "📊 3-Month Milestones" "🏃 2-Week Sprint" "✅ Daily Tasks" "🚫 Not-To-Do"; do
  curl -s -X POST "https://api.todoist.com/rest/v2/projects" \
    -H "Authorization: Bearer $TODOIST_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"name\": \"$project\"}"

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The local backend writes long-term planning files to disk under a predictable path in the user's home directory. These files may contain sensitive goals, habits, and reviews, so unattended persistence can expose personal data to other local users, sync tools, or malware.

Content

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

bash
echo "BACKEND=local" > ~/.config/4to1/config
echo "LOCAL_DIR=~/4to1-plans" >> ~/.config/4to1/config
mkdir -p ~/4to1-plans/{vision,milestones,sprints,daily,not-to-do}

Core Commands

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The search request queries Notion content remotely using the stored token, which can reveal account metadata and workspace contents beyond a single planning page. In a broadly triggered skill, even read operations can expose private user data to unintended processing flows.

Content

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

md
NOTION_KEY=$(grep NOTION_API_KEY ~/.config/4to1/config | cut -d= -f2)

# Search planning pages
curl -s -X POST "https://api.notion.com/v1/search" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The search request queries Notion content remotely using the stored token, which can reveal account metadata and workspace contents beyond a single planning page. In a broadly triggered skill, even read operations can expose private user data to unintended processing flows.

Content

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

md
NOTION_KEY=$(grep NOTION_API_KEY ~/.config/4to1/config | cut -d= -f2)

# Search planning pages
curl -s -X POST "https://api.notion.com/v1/search" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

Querying a Notion database retrieves potentially sensitive project data, status, dates, and notes from a remote service. Because the skill can be activated by broad planning language, this remote read path is more dangerous than in a narrowly scoped admin tool.

Content

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

md
-d '{"query": "4To1"}'

# Query projects by layer
curl -s -X POST "https://api.notion.com/v1/databases/{db_id}/query" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

Updating Notion pages modifies remote user data using a bearer token, which can alter progress tracking and status values without a strong confirmation boundary. Unauthorized or accidental writes could corrupt planning records or create misleading history.

Content

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

md
]}}'

# Update progress
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

Creating sprint log entries establishes persistent storage of reflections and energy levels in a third-party system across sessions. This is not inherently malicious, but it is privacy-sensitive and should be treated as persistent behavioral data collection.

Content

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

md
-H "Content-Type: application/json" \
  -d '{"properties": {"Progress": {"number": 0.75}, "Status": {"select": {"name": "Active"}}}}'

# Create sprint log entry
curl -s -X POST "https://api.notion.com/v1/pages" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

Creating sprint log entries writes reflections and productivity metrics to Notion, persisting potentially sensitive self-assessment data externally. The skill context makes this more sensitive because coaching conversations often elicit personal details users may not expect to be stored remotely.

Content

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

md
-d '{"properties": {"Progress": {"number": 0.75}, "Status": {"select": {"name": "Active"}}}}'

# Create sprint log entry
curl -s -X POST "https://api.notion.com/v1/pages" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The Todoist project and task retrieval calls access remote account data using bearer authentication. Read access is still sensitive here because the skill could ingest personal task metadata when the user only intended conversational planning assistance.

Content

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

md
TODOIST_KEY=$(grep TODOIST_API_KEY ~/.config/4to1/config | cut -d= -f2)

# Get all projects
curl -s "https://api.todoist.com/rest/v2/projects" -H "Authorization: Bearer $TODOIST_KEY"

# Get active tasks in a project
curl -s "https://api.todoist.com/rest/v2/tasks?project_id={id}" -H "Authorization: Bearer $TODOIST_KEY"

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The Todoist project and task retrieval calls access remote account data using bearer authentication. Read access is still sensitive here because the skill could ingest personal task metadata when the user only intended conversational planning assistance.

Content

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

md
TODOIST_KEY=$(grep TODOIST_API_KEY ~/.config/4to1/config | cut -d= -f2)

# Get all projects
curl -s "https://api.todoist.com/rest/v2/projects" -H "Authorization: Bearer $TODOIST_KEY"

# Get active tasks in a project
curl -s "https://api.todoist.com/rest/v2/tasks?project_id={id}" -H "Authorization: Bearer $TODOIST_KEY"

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

Fetching active tasks from Todoist reads potentially sensitive user workload and schedule metadata from a third-party account. In combination with broad activation triggers, this can expose remote personal data during ordinary planning chats.

Content

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

md
curl -s "https://api.todoist.com/rest/v2/projects" -H "Authorization: Bearer $TODOIST_KEY"

# Get active tasks in a project
curl -s "https://api.todoist.com/rest/v2/tasks?project_id={id}" -H "Authorization: Bearer $TODOIST_KEY"

# Create task linked to sprint
curl -s -X POST "https://api.todoist.com/rest/v2/tasks" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

Creating Todoist tasks pushes user content to an external service and can change real task state in the user's account. If triggered unintentionally, it may create unwanted tasks or leak planning details to the connected service.

Content

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

md
curl -s "https://api.todoist.com/rest/v2/tasks?project_id={id}" -H "Authorization: Bearer $TODOIST_KEY"

# Create task linked to sprint
curl -s -X POST "https://api.todoist.com/rest/v2/tasks" \
  -H "Authorization: Bearer $TODOIST_KEY" -H "Content-Type: application/json" \
  -d '{"content": "Task name", "project_id": "xxx", "priority": 4, "due_string": "next monday", "description": "Sprint: 2-Week Sprint | Milestone: Q1 Goal"}'

Static analysis

No suspicious patterns detected.