Back to skill

Security audit

planning-toolkit

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent planning helper, but its setup script can write and delete files outside the intended planning folder if given a crafted task slug.

Review this before installing. It does not show exfiltration or deception, but only use the initialization script with simple slugs such as lowercase words, digits, and hyphens until the slug validation/path traversal issue is fixed. Be aware that it creates persistent local planning files and may guide the agent into iterative work or cleanup passes.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/init-planning.sh:30
Finding

Unrestricted Task Slug Allows Path Traversal and File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/init-planning.sh, lines 30–73
Vulnerability Type: Path traversal and arbitrary fixed-name file overwrite
Risk Level: Medium

Vulnerable Code

bash
SLUG="$1"
PLAN_DIR=".planning/${DATE}-${SLUG}"

# Check if directory already exists
if [ -d "$PLAN_DIR" ]; then
  echo "Warning: Planning directory already exists: $PLAN_DIR"
  read -p "Overwrite? (y/N) " -n 1 -r
  echo
  if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "Aborted."
    exit 0
  fi
fi

# Create directory
mkdir -p "$PLAN_DIR"

# Copy templates
cp "$TEMPLATES_DIR/task_plan.md" "$PLAN_DIR/"
cp "$TEMPLATES_DIR/findings.md" "$PLAN_DIR/"
cp "$TEMPLATES_DIR/progress.md" "$PLAN_DIR/"

# Replace placeholders with task slug
TASK_NAME=$(echo "$SLUG" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1')

# Update task_plan.md
sed -i.bak "s/\[TASK_NAME\]/$TASK_NAME/g" "$PLAN_DIR/task_plan.md"
rm -f "$PLAN_DIR/task_plan.md.bak"

# Update findings.md
sed -i.bak "s/\[TASK_NAME\]/$TASK_NAME/g" "$PLAN_DIR/findings.md"
rm -f "$PLAN_DIR/findings.md.bak"

# Update progress.md
sed -i.bak "s/\[TASK_NAME\]/$TASK_NAME/g" "$PLAN_DIR/progress.md"
rm -f "$PLAN_DIR/progress.md.bak"

# Update timestamps
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
sed -i.bak "s/\[YYYY-MM-DD HH:MM\]/$TIMESTAMP/g" "$PLAN_DIR/task_plan.md"
sed -i.bak "s/\[YYYY-MM-DD HH:MM\]/$TIMESTAMP/g" "$PLAN_DIR/findings.md"
sed -i.bak "s/\[YYYY-MM-DD HH:MM\]/$TIMESTAMP/g" "$PLAN_DIR/progress.md"
rm -f "$PLAN_DIR/"*.bak

Technical Analysis

The script incorporates the first command-line argument directly into PLAN_DIR without enforcing a slug grammar or verifying the canonical destination path:

bash
PLAN_DIR=".planning/${DATE}-${SLUG}"

Although the path is quoted, quoting only prevents shell word splitting and glob expansion. It does not prevent filesystem traversal through slash-separated .. components. A slug containing a normal component follow ...[truncated 2504 chars]

Remediation
View remediation

Remediation Suggestions

  1. Enforce a strict slug grammar before constructing any path.

    Accept only lowercase letters, digits, and internal hyphens, with a bounded length:

    bash
    SLUG="$1"
    
    if [[ ! "$SLUG" =~ ^[a-z0-9][a-z0-9-]{0,63}$ ]]; then
      echo "Error: task slug must contain only lowercase letters, digits, and hyphens."
      exit 1
    fi
    
  2. Reject path-related and control characters explicitly.

    The validation must reject /, \, .., whitespace, newlines, shell metacharacters, and empty normalized values. A strict allowlist is preferable to maintaining a denylist.

  3. Verify the canonical destination remains below .planning.

    Resolve both the planning root and intended destination to canonical absolute paths, then verify that the destination begins with the planning root plus a path separator before performing writes.

  4. Avoid broad wildcard deletion.

    Replace:

    bash
    rm -f "$PLAN_DIR/"*.bak
    

    with explicit removal of only the backup files created by the script:

    bash
    rm -f \
      "$PLAN_DIR/task_plan.md.bak" \
      "$PLAN_DIR/findings.md.bak" \
      "$PLAN_DIR/progress.md.bak"
    
  5. Escape values used in sed replacement expressions.

    Escape backslashes, ampersands, and the selected delimiter before interpolating TASK_NAME, or use a language with safer literal string replacement semantics.

  6. Fail safely on existing destination files.

    Prefer creating a new directory atomically and refusing to overwrite existing files unless an explicit noninteractive overwrite option is supplied by the trusted caller.

  7. Add regression tests.

    Tests should confirm rejection of traversal and malformed inputs, including:

    text
    ../target
    x/../../../target
    /tmp/target
    x\..\target
    task/name
    task&name
    task followed by a newline
    
Vulnerability Patterns
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The declared description promises a comprehensive planning toolkit spanning specification, planning, iterative execution, and self-cleaning/optimization. The supplied code only bootstraps a directory structure and templated markdown files for planning. It does not analyze requirements, generate plans, execute tasks, iterate autonomously, or optimize/clean up beyond removing temporary .bak files created during placeholder substitution. That cleanup is incidental implementation detail, not the declared autonomous cleanup capability. Therefore the description materially overstates the code’s actual behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

声明描述的是一个覆盖“做什么、怎么拆、怎么做、怎么优化”的完整规划与执行工具包,但提供的代码片段实际只是一个迭代循环状态控制器。它管理 loop-state.json 的生命周期,提供 init/check/update/complete 四个子命令,并基于迭代次数、正则、文件存在或文件变更等条件决定是否继续。这与高层“规划工具包”目标存在明显范围差异:代码没有需求规格分析、任务分解、执行任务、清理优化等核心能力。虽然‘迭代执行’中的循环控制可被视为整体系统的一个支撑模块,但单看该代码,其实际行为不足以准确代表所声明的完整用途,因此应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% 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 · scripts/init-planning.sh (reported line 58)May include surrounding context.

sh
# Update task_plan.md
sed -i.bak "s/\[TASK_NAME\]/$TASK_NAME/g" "$PLAN_DIR/task_plan.md"
rm -f "$PLAN_DIR/task_plan.md.bak"

# Update findings.md
sed -i.bak "s/\[TASK_NAME\]/$TASK_NAME/g" "$PLAN_DIR/findings.md"

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% 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 · scripts/init-planning.sh (reported line 62)May include surrounding context.

sh
# Update findings.md
sed -i.bak "s/\[TASK_NAME\]/$TASK_NAME/g" "$PLAN_DIR/findings.md"
rm -f "$PLAN_DIR/findings.md.bak"

# Update progress.md
sed -i.bak "s/\[TASK_NAME\]/$TASK_NAME/g" "$PLAN_DIR/progress.md"

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% 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 · scripts/init-planning.sh (reported line 66)May include surrounding context.

sh
# Update progress.md
sed -i.bak "s/\[TASK_NAME\]/$TASK_NAME/g" "$PLAN_DIR/progress.md"
rm -f "$PLAN_DIR/progress.md.bak"

# Update timestamps
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

This cleanup uses a wildcard against a path component influenced by user input: rm -f "$PLAN_DIR/"*.bak. Because the glob is outside the quotes, a slug containing wildcard characters like * or ? can cause expansion over multiple matching directories under .planning, leading to unintended deletion of .bak files beyond the intended plan directory. In a developer tool that operates on local files, that makes the issue more plausible and impactful than in a fixed-path script.

Content

Scanner excerpt · scripts/init-planning.sh (reported line 73)May include surrounding context.

sh
sed -i.bak "s/\[YYYY-MM-DD HH:MM\]/$TIMESTAMP/g" "$PLAN_DIR/task_plan.md"
sed -i.bak "s/\[YYYY-MM-DD HH:MM\]/$TIMESTAMP/g" "$PLAN_DIR/findings.md"
sed -i.bak "s/\[YYYY-MM-DD HH:MM\]/$TIMESTAMP/g" "$PLAN_DIR/progress.md"
rm -f "$PLAN_DIR/"*.bak

# Create .active_plan pointer
echo "$PLAN_DIR" > .planning/.active_plan

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill metadata description and the full instructional content are presented exclusively in Chinese, which effectively imposes a locale/language choice on users without any opt-in or alternative. Under the stated policy, language constraints should either be user-selectable or clearly justified as region-specific, neither of which is documented here.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The iterative-mode trigger phrases are broad enough that ordinary user requests about planning or improvement could unintentionally activate looping behavior. In an agentic environment, this can cause unintended repeated actions, extra file writes, unnecessary tool usage, or prolonged autonomous execution beyond the user's intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This is a natural-language policy issue because the file forces a specific language for its docstring, usage instructions, help text, and runtime messages. Users who do not read Chinese are not given an opt-in, alternative locale, or explanation that the skill is intended only for a Chinese-speaking context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The default value for the "name" field is the Chinese string "任务名称", which embeds a specific language choice in a general-purpose template. Because the file does not state that the template is intended only for Chinese-language use or offer an opt-in language choice, this can conflict with language/locale policy expectations.

Content

No source excerpt is available for this finding.