Back to skill

Security audit

Feishu Sync Obsidian Local

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent Feishu-to-Obsidian sync purpose, but its write helper can create files outside the intended vault if its JSON input or sync rules are manipulated.

Install only if you trust the Feishu workspace and the agent/tools that supply write-mode JSON. Before use, fix or constrain scripts/sync.py so all destination paths resolve under VAULT_DIR, filenames are basenames ending in .md, and write mode uses destinations from the cached plan rather than caller-provided paths. Avoid enabling any automatic systemd sync or AGENTS.md persistence unless you explicitly want that behavior, and be careful sharing synced notes because Feishu identifiers are written into frontmatter.

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/sync.py:195
Finding

Unvalidated destination paths permit arbitrary file writes outside the Obsidian vault

Content
View full analysis
Path: dest_dir = VAULT_DIR / relative_path dest_dir.mkdir(parents=True, exist_ok=True) return dest_dir ``` ```python def write_obsidian_file(relative_path: str, filename: str, title: str, content: str, doc_token: str, node_token: str, wiki_name: str, dry_run: bool = False) -> Optional[str]: """Write an Obsidian file, returning its path or None if it exists.""" content = convert_lark_tables(content) existing = find_existing_by_doc_token(doc_token) if existing: print(f" [SKIP] {title} → already exists ({existing.name})") return None dest_dir = ensure_obsidian_folder(relative_path) dest_path = dest_dir / filename counter = 1 while dest_path.exists() and counter < 100: base, ext = filename.rsplit(".", 1) dest_path = dest_dir / f"{base}-{counter}.{ext}" counter += 1 if dry_run: print(f" [DRY-RUN] {title} → {relative_path}/{filename}") return str(dest_path) frontmatter = build_frontmatter(doc_token, node_token, wiki_name) dest_path.write_text(f"{frontmatter}\n\n{content}", encoding="utf-8") print(f" [SYNCED] {title} → {relative_path}/{dest_path.name}") return str(dest_path) ``` ```python todo = json.loads((CACHE_DIR / "plan.json").read_text())["todo"] todo_map: Dict[str, dict] = {t["obj_token"]: t for t in todo} all_synced, skipped, failed = [], 0, [] for node in nodes: title = node.get("title", "Unnamed") obj_token = node.get("obj_token", "") content = node.get("content", "") node_token = node.get("node_token", "") wiki_name = node.get("wiki_name", "") relative_path = node.get("relative_path" ...[truncated 3462 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (13)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
## 核心设计

**内容获取由 Agent 的 feishu_fetch_doc 工具完成,Python 脚本只做路径构建和文件写入。**
这样无需在脚本里管理 Access Token,也不需要在 clawhub 发布时携带敏感权限。

---

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill performs sensitive local operations such as reading configuration files, creating directories, and writing synchronized content into the user's vault, but it does not declare an explicit tool scope or allowed-tools boundary. Without a declared permission model, an agent runtime may grant broader file or environment access than intended, increasing the blast radius if the skill is mis-triggered or its instructions are abused.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger phrase “同步文档” is overly broad and can match ordinary conversation unrelated to this skill, causing the sync workflow to start unintentionally. Because the skill can read configuration, fetch remote content, and write files locally, accidental invocation can lead to unintended data retrieval or modification of the user's knowledge base.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs unconditional persistence of Feishu document and node tokens into frontmatter of user-visible notes. These identifiers may be sensitive internal references that enable correlation of documents, leak workspace structure, or be exfiltrated later through vault sharing, sync services, publishing, or plugins.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The title and all user-facing instructions in this template are written exclusively in Chinese, and references to invocation text such as '告诉小墨"同步飞书"' imply a fixed language for use. There is no indication that users may choose another language or that the locale restriction is intentionally limited to a Chinese-only environment.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manual trigger phrase includes very generic language like “同步文档”, which can be invoked during ordinary conversation rather than an intentional sync request. In this skill, triggering starts a multi-step synchronization workflow that can create directories, write files, and update sync state, so accidental activation can cause unintended filesystem changes or data import.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The entire document is written exclusively in Chinese and provides no indication that language selection is optional or that the skill is intentionally limited to a Chinese-only audience for a documented regional reason. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

该文件通篇以中文规定审查清单和输出格式,未说明是否允许按用户语言偏好输出,也未提供语言选择或适用范围说明。根据 SQP-3,强制特定语言而无用户选择或明确、合理的区域性约束,属于自然语言政策风险。

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

该 markdown 文件适用 SQP-1。L88-L90 的触发条件包含“每次同步执行后自动触发”“用户要求‘检查同步结果’时触发”“发现同步问题时触发”,其中“发现同步问题时触发”边界不清,且未说明由谁判定、在何种输入或流程阶段触发,容易造成模糊调用。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The document marks itself as deprecated at L03 and labels the old file rules as '已废弃' later, but lines L07-L46 still document the '当前规则来源', active matching logic, Wiki Space configuration, and sync direction as operative behavior. This creates an intent/documentation contradiction inside the file: readers are told the file is obsolete while also being instructed to use its contents as current configuration.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The document is entirely written in Chinese and presents the routing rules only in that language, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking context. Under the stated policy, forcing a specific language without opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring says '纯路径构建 + 文件写入工具' and emphasizes that Step A only returns a pending write list. In practice, mode_plan persists plan.json under /tmp, so the script performs additional stateful filesystem writes beyond the documented 'return list' behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a 4-step pipeline for syncing Feishu Wiki documents into an Obsidian PARA knowledge base, with SYNC-RULES.md in the vault as the required control file. However, the code also creates and uses /tmp/feishu-sync-obsidian as an external state store, introducing filesystem side effects outside the vault that are not mentioned in the skill purpose or documentation as necessary scope.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.