Back to skill

Security audit

4To1 Planner - AI Planning Coach

Security checks for vulnerabilities and agentic risk

Overview

The planner's purpose is coherent, but it needs review because its setup/status scripts handle account tokens unsafely and can execute local config contents as shell code.

Review this skill before installing. Use the local Markdown backend if you want the lowest account risk, and do not run the setup/status scripts with real tokens until credential storage is hardened, the config is parsed as data rather than sourced, and external writes require explicit confirmation.

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

Warning
Location
scripts/setup.sh:24
Finding

API Tokens Are Collected Visibly and Stored Without Explicit Access Restrictions

Content
View full analysis
> "$CONFIG_DIR/config" echo "" echo "5. In Notion, create or open the page where you want your planning hub" echo "6. Click ··· → Connections → select '4To1 Planner'" echo "7. Copy the page ID from the URL (the 32-char hex string after the page name)" echo "" read -p "Paste the parent page ID: " parent_page echo "NOTION_PARENT_PAGE=$parent_page" >> "$CONFIG_DIR/config" ``` ```bash echo "📋 Todoist Setup:" echo "1. Go to https://app.todoist.com/app/settings/integrations/developer" echo "2. Copy your API token" echo "" read -p "Paste your Todoist API token: " todoist_key echo "TODOIST_API_KEY=$todoist_key" >> "$CONFIG_DIR/config" ``` ### Technical Analysis The setup script uses ordinary `read -p` prompts for Notion and Todoist credentials. This causes the credentials to remain visible while they are typed and may expose them to screen recording, shoulder surfing, terminal capture, or other monitoring of the interactive session. The credentials are subsequently written in plaintext under `~/.config/4to1/config`. The script does not establish a restrictive `umask`, assign mode `0700` to the configuration directory, or assign mode `0600` to the credential file. The actual permissions therefore depend on the invoking user's environment and default `umask`. Under a permissive configuration, other local a ...[truncated 1528 chars]
Remediation
View remediation
> "$CONFIG_DIR/config" ``` 4. Prefer an operating-system credential store, such as macOS Keychain, Secret Service, or an equivalent secure secret manager. Keep only non-sensitive backend selection and identifiers in the configuration file. 5. Validate expected token formats before storage and reject line breaks, shell metacharacters, or unexpected control characters. 6. Document the credential scope required by the Skill and advise users to grant the minimum possible Notion integration access. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/status.sh:4
Finding

Untrusted Configuration Values Are Executed as Shell Code

Content
View full analysis
> "$CONFIG_DIR/config" echo "" echo "5. In Notion, create or open the page where you want your planning hub" echo "6. Click ··· → Connections → select '4To1 Planner'" echo "7. Copy the page ID from the URL (the 32-char hex string after the page name)" echo "" read -p "Paste the parent page ID: " parent_page echo "NOTION_PARENT_PAGE=$parent_page" >> "$CONFIG_DIR/config" ``` ```bash read -p "Paste your Todoist API token: " todoist_key echo "TODOIST_API_KEY=$todoist_key" >> "$CONFIG_DIR/config" ``` The status script then executes the configuration as shell input: ```bash CONFIG="$HOME/.config/4to1/config" if [ ! -f "$CONFIG" ]; then echo "❌ Not configured. Run: bash {baseDir}/scripts/setup.sh" exit 1 fi source "$CONFIG" ``` ### Technical Analysis `source "$CONFIG"` does not parse the file as passive key-value data. It executes every line in the file in the current shell process. Meanwhile, `setup.sh` serializes user-provided values without validating or safely shell-quoting them. A value containing shell syntax can therefore be stored as part of an assignment and interpreted when `status.sh` later sources the file. For example, if a user is induced to paste a purported token containing command substitution, the generated configuration can contain: ```bash NOTION_API_KEY=$(attacker_command) ``` The command substitution is not executed when the value is initially expanded by `echo`, but it is preserved in the generated text. It is executed later when the configuration file is sourced. The same execution ...[truncated 1674 chars]
Remediation
View remediation
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
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 connecting to Notion, Todoist, and Google Calendar and says the AI 'reads' those tools automatically, but it does not present a clear user-facing warning about what data will be accessed, stored, or shared. In a planning skill, these integrations likely expose sensitive personal schedules, goals, notes, and tasks, so missing privacy and permission disclosures can lead users to grant broad access without informed consent.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises shell-capable setup and operational commands but declares no explicit tool scope or permission boundary. That mismatch is dangerous because an agent may be induced to execute filesystem writes, network calls, and local scripts without transparent user consent or platform enforcement.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation phrases are very broad and overlap with common productivity requests, increasing the chance the skill triggers when the user did not intend backend access or data modification. In this skill, unintended activation is more dangerous because activation can lead to credential use, persistent writes, and external API operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill stores sensitive personal planning data, writes to local files, and performs third-party account operations without clear upfront disclosure of privacy, persistence, and side effects. Users may expose long-term goals, habits, and account data without understanding where it is stored or transmitted.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
91% confidence
Finding

The skill instructs persistent storage of API keys in a local plaintext config file under the user's home directory. This creates a durable secret exposure surface to other local processes, future agent actions, backups, or accidental disclosure.

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

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill instructs extracting API keys from a local config file via shell, which gives the agent a credential-access pattern unrelated to simple conversational planning. Once normalized, this enables secret handling and possible exfiltration through subsequent API calls or logs.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
83% confidence
Finding

This finding reflects persistent creation of remote planning artifacts in Notion, which extends the effect of a single session into long-lived external state. Persistence is expected for a planner, but still needs explicit consent because it changes and retains user data beyond the conversation.

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
87% confidence
Finding

This command sends authenticated requests to Notion, transmitting user planning content and identifiers to an external service. External transmission is expected for a Notion integration, but it remains security-relevant because it combines sensitive personal data with credentialed API access.

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
87% confidence
Finding

This command sends authenticated requests to Notion, transmitting user planning content and identifiers to an external service. External transmission is expected for a Notion integration, but it remains security-relevant because it combines sensitive personal data with credentialed API access.

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
85% confidence
Finding

Creating a Notion database is an authenticated external write that persists user planning structure in a third-party workspace. That is expected for the backend, but it can have privacy and integrity consequences if initiated without explicit approval.

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
85% confidence
Finding

This command creates another Notion database and persists review/energy data externally. Because the data includes reflective and behavioral information, the privacy sensitivity is higher than a generic productivity action.

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
86% confidence
Finding

The Todoist project-creation loop performs authenticated external writes that modify a third-party account. While aligned with the stated integration purpose, it can still create unintended state changes if triggered accidentally or without clear approval.

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
86% confidence
Finding

The Todoist project-creation loop performs authenticated external writes that modify a third-party account. While aligned with the stated integration purpose, it can still create unintended state changes if triggered accidentally or without clear approval.

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\"}"

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Invoking a local Python setup script expands the skill from planning assistance into arbitrary local code execution. Even if intended for OAuth bootstrap, this creates a broad execution surface that can run unreviewed code or spawn further subprocesses.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
87% confidence
Finding

The local backend creates persistent directories and files under the user's home directory, storing long-term planning and reflective data. This is contextually aligned with a planner, but it increases privacy risk if done without clear notice and consent.

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
84% confidence
Finding

The Notion search operation transmits authenticated queries to an external API and may reveal workspace structure or planning artifacts. Even read-oriented calls are sensitive because they disclose account metadata and user content outside the local session.

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
84% confidence
Finding

The Notion search operation transmits authenticated queries to an external API and may reveal workspace structure or planning artifacts. Even read-oriented calls are sensitive because they disclose account metadata and user content outside the local session.

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
84% confidence
Finding

Querying a Notion database sends authenticated filters and retrieves structured planning records from an external service. This is contextually justified, but still security-relevant because it accesses potentially sensitive user plans and progress data.

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
85% confidence
Finding

Updating progress in Notion is an authenticated external state change affecting user records. In a skill with broad triggers, such writes could happen unexpectedly and alter the user's planning system without deliberate approval.

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
82% confidence
Finding

Creating sprint log entries in Notion persists reflective session data across time in a third-party service. The persistence itself is intended, but it is security-relevant because it stores potentially sensitive behavioral information outside the transient chat context.

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
85% confidence
Finding

Creating a sprint log entry transmits behavioral and reflective data to Notion and persists it externally. This is part of the feature set, but still risky due to the sensitivity of personal review content and the possibility of accidental execution.

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
84% confidence
Finding

Fetching Todoist projects and tasks transmits account-scoped authenticated requests to an external service, exposing task metadata and project structure. In context this is functionally necessary, but still risky because broad triggers could cause unexpected data access.

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
84% confidence
Finding

Fetching Todoist projects and tasks transmits account-scoped authenticated requests to an external service, exposing task metadata and project structure. In context this is functionally necessary, but still risky because broad triggers could cause unexpected data access.

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
85% confidence
Finding

Fetching tasks from Todoist performs authenticated external reads of potentially sensitive task data. It fits the declared integration, but still exposes account data access behavior that should not occur on ambiguous activation.

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" \

Static analysis

No suspicious patterns detected.