Back to skill

Security audit

Zettelkasten CN

Security checks for vulnerabilities and agentic risk

Overview

This looks like a local note-management skill, but its undo feature can move or overwrite files outside the intended notes folder if history records are forged or misused.

Review before installing. Use only in a constrained workspace or after fixing the undo system: restrict or remove the internal log command, validate all undo paths against the notes and trash directories, and avoid trusting serialized paths from operation_history.json.

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

Error
Location
scripts/undo_manager.py:113
Finding
Arbitrary File Move and Overwrite Through Forged Undo Records<![CDATA[ ## Vulnerability Details **File Location**: `scripts/undo_manager.py`, lines 113–117, 127–132, 146–152, 167–175, and 224–229 **Vulnerability Type**: Unvalidated path use in privileged filesystem operations **Risk Level**: High ### Vulnerable Code Lines 113–117 allow a path from an operation record to be moved without verifying that it belongs to the card repository: ```python file_path = Path(details.get("path", "")) if file_path.exists(): trash_path = TRASH_DIR / file_path.name shutil.move(str(file_path), str(trash_path)) ``` Lines 127–132 restore a file to an arbitrary destination supplied by the operation record: ```python original_path = Path(details.get("original_path", "")) trash_path = Path(details.get("trash_path", "")) if trash_path.exists(): original_path.parent.mkdir(parents=True, exist_ok=True) shutil.move(str(trash_path), str(original_path)) ``` Lines 146–152 repeat the same issue for batch restoration: ```python original_path = Path(item.get("original_path", "")) trash_path = Path(item.get("trash_path", "")) if trash_path.exists(): try: original_path.parent.mkdir(parents=True, exist_ok=True) shutil.move(str(trash_path), str(original_path)) ``` Lines 167–175 overwrite an existing file with content taken directly from the history record: ```python file_path = Path(details.get("path", "")) backup_content = details.get("backup_content", "") if file_path.exists() and backup_content: current_content = file_path.read_text(encoding='utf-8') file_path.write_text(backup_content, encoding='utf-8') ``` Lines 224–229 expose a command that accepts arbitrary JSON and stores it as an operation record: ```python elif args.command == "log": details = json.loads(args.details) if args.details else {} op_id = log_operation(args.type, details) print(json.dumps({"success": True, "op_id": op_id}, ensure_ascii=False)) ``` ### Technical Analysis The undo subsystem treats data stored in `.syst ...[truncated 2958 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Remove or restrict the `log` command** - Do not expose the internal history-writing interface as an unrestricted CLI command. - If it must remain available, enforce a fixed schema for each operation type and reject unknown fields or operation types. - Do not treat possession of a valid JSON object as authorization to perform filesystem operations. 2. **Enforce path containment** - Resolve every source and destination with `Path.resolve()`. - Require card paths and restore destinations to remain under `CARDS_DIR.resolve()`. - Require restore sources to remain under `TRASH_DIR.resolve()`. - Reject absolute or relative paths that resolve outside these approved roots. ```python def require_within(path: Path, root: Path) -> Path: resolved_path = path.expanduser().resolve(strict=False) resolved_root = root.expanduser().resolve(strict=True) if not resolved_path.is_relative_to(resolved_root): raise ValueError(f"Path is outside the approved root: {resolved_path}") return resolved_path ``` 3. **Validate paths according to operation type** - For `create` undo records, require the source to be an approved Markdown card under a recognized card directory. - For `delete` and `batch_delete`, require the source to be inside `TRASH_DIR` and the destination to be inside an approved note directory. - For `update`, require the target to be an approved Markdown card under `CARDS_DIR`. 4. **Reject symbolic-link attacks** - Reject symlink sources and destinations. - Validate resolved paths immediately before each move or write to reduce time-of-check/time-of-use exposure. - Use filesystem operations that avoid following symlinks where supported. 5. **Avoid trusting serialized paths** - Store an immutable card identifier and operation identifier rather than arbitrary absolute paths. - Reconstruct approved paths from trusted application state when performing an undo. - Co ...[truncated 672 chars]
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • 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 (55)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The code substantially matches the general purpose of managing Zettelkasten-style notes with CRUD, categorization, linking, search, and conversion. However, several declared capabilities are overstated or not actually implemented in this chunk. Most notably, '与Agent记忆系统的双向关联' is not supported: the script only stores memory_refs inside notes and searches notes by memory date; it does not read/write actual Agent memory data or synchronize both directions. '支持撤销操作' is only represented by logging create/delete operations to undo_manager.py, without implementing undo behavior here. '交互式创建流程' is also not present as an interactive wizard, only as command-line subcommands and flags. Additionally, the code includes a fifth note type ('map') beyond the declared four. These are material description/behavior mismatches, though the primary domain remains related.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
该代码块的实际用途非常狭窄,集中在“撤销管理”子功能:将操作记录写入 operation_history.json,把删除/创建相关文件移入或移出 .system/trash,并支持恢复更新前内容。虽然声明中提到“支持撤销操作”,因此这部分并不矛盾,但整体描述将该技能表述为完整的 Zettelkasten 生命周期管理系统,涵盖分类、交互式创建、各类笔记 CRUD、以及 Agent 记忆双向关联;这些核心能力在提供的代码中均未体现。故描述对该代码块的代表性不足,存在明显不匹配。

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill documents shell execution and filesystem read/write behavior but does not declare any explicit tool scope or permissions boundary. In an agent environment, this creates ambiguous authority and increases the chance that the skill is invoked with broader file or shell access than users expect, especially given its ability to create, update, delete, and clear history in a desktop-backed notes store.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The natural-language content of the skill forces a single language experience for description and operational guidance, with no user opt-in or alternative locale. Under the stated policy, a fixed language is a violation unless the skill offers a choice or clearly documents a justified region-specific constraint.

Session Persistence

Medium
Category
Rogue Agent
Content
cd /path/to/zettelkasten

# 创建笔记
python3 scripts/card_manager.py create fleeting "闪念标题" --content "内容"
python3 scripts/card_manager.py create permanent "笔记标题" --category 学习

# 查询
Confidence
83% confidence
Finding
The documented behavior creates persistent local records of user inputs, note contents, and operation history. Persistent storage is not inherently malicious, but in a security review it matters because sensitive thoughts, reading notes, or memory associations may remain on disk and be recoverable later from the primary store, history, or trash, increasing exposure beyond the immediate session.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill advertises destructive commands such as delete and history clear without explicit warnings, confirmation guidance, or safeguards. In an agent-assisted context, users may trigger irreversible or hard-to-recover local data loss, especially because the skill operates on persistent files under the user's Desktop and also manages undo/history state.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The markdown template includes fixed Chinese text for the section heading and checklist content, which imposes a specific language on all generated notes. The file does not offer a language choice or document that the template is intentionally limited to a Chinese-speaking context.

Static analysis

No suspicious patterns detected.