Back to skill

Security audit

Focus Tree

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed local focus-tracking helper that writes project status files, with some prompt-context hygiene risks users should understand.

Install only if you want the agent to maintain local FOCUS.md and FOCUS-LOG.md files in your workspace. Review those files periodically, be cautious with untrusted pasted task text, and confirm before archiving or clearing focus state if the current context matters.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

T02 · Agent Memory Poisoning

Warning
Location
scripts/focus.mjs:27
Finding
Persistent Agent Memory Poisoning Through Unsanitized Focus-State Fields## Vulnerability Details **File Location**: `scripts/focus.mjs:27-44, 107-110, 124, 135, 165`; related trust instructions in `SKILL.md:24-26, 61-66` **Vulnerability Type**: Persistent agent memory poisoning through unsanitized Markdown content **Risk Level**: Medium ### Vulnerable Code ```js function generateFocus(focusPoint, todos = [], context = '', status = 'active') { // ... let output = `# FOCUS.md - 当前聚焦\n\n`; output += `🎯 **Focus Point**: ${focusPoint || '无'}\n\n`; output += `**Started:** ${new Date().toISOString().split('T')[0]}\n`; output += `**Status:** ${stateIcons[status] || '🟢'} ${status}\n\n`; if (todos.length > 0) { output += `📝 TODOs\n`; todos.forEach(todo => { const icon = todo.done ? '✅' : '☐'; output += `${icon} ${todo.content}\n`; }); output += `\n`; } output += `📖 Context\n`; output += context || '无\n'; output += `\n---\n*最后更新: ${now}*\n`; return output; } ``` ```js const entry = `\n## ${statusEmoji} ${data.focusPoint} — ${archiveType} ${completedDate}\n**Started:** ${data.started || completedDate}\n**Outcome:** ${outcome || '任务完成'}\n**Status:** ${allCompleted ? '全部完成' : '未完成'}\n`; ``` ```js case 'init': const focusPoint = args.slice(1).join(' ') || '新项目'; fs.writeFileSync(FOCUS_PATH, generateFocus(focusPoint, [], '', 'active')); console.log('✅ FOCUS.md created:', focusPoint); break; case 'add-todo': const data = parseFocus(); if (!data) { console.error('❌ No FOCUS.md found. Run "init" first.'); process.exit(1); } data.todos.push({ done: false, content: args.slice(1).join(' ') }); fs.writeFileSync(FOCUS_PATH, generateFocus(data.focusPoint, data.todos, data.context, data.status)); console.log('✅ Todo added'); break; ``` ```js case 'archive': archive(args.slice(1).join(' ')); break; ``` The related documentation establishes the generated file as trusted persistent agent context: ```markdown ## When to Read FOCUS.md - **Every session start** (be ...[truncated 2752 chars]
Remediation
## Remediation Suggestions 1. Treat all focus points, TODO text, context, and archive outcomes as untrusted data. 2. Reject or normalize control characters and embedded carriage returns or newlines for fields intended to occupy one line. 3. Escape Markdown metacharacters before rendering values, or store state in a strictly validated JSON document and render Markdown only for display. 4. Define a schema with field types, maximum lengths, and allowed character policies; reject values that do not conform. 5. Clearly delimit user-controlled values and add explicit instructions that agents must never interpret stored task content as operational or safety instructions. 6. Keep data and instructions in separate channels where supported. Agents should treat loaded focus-state values as quoted records rather than authoritative directives. 7. Apply the same validation to archive outcomes and any context imported from existing files. 8. Add regression tests using inputs containing newlines, headings, section delimiters, instruction-like phrases, and oversized content to verify that they cannot alter document structure.
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill instructs the agent to directly create, edit, clear, and archive files in the user workspace as part of normal operation, but it does not require explicit user confirmation before modifying local files. In an agent setting, persistent file writes can overwrite user context, create unwanted state, or alter project artifacts based on inferred intent rather than an explicit authorization boundary.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The manifest and main documentation describe the skill as extracting decisions, TODOs, constraints, blockers, and sub-agents into a tree structure, which implies conversational extraction. However, the HEARTBEAT.md section explicitly states 'No Auto-extraction' and says to 'Only update on explicit trigger conditions,' creating a direct contradiction in documented intent. This is an intent-level divergence within the skill documentation.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The manifest describes persistent hierarchical task tracking that extracts decisions, TODOs, constraints, blockers, and sub-agents into a tree structure. This script only creates and rewrites two Markdown files with a single focus point, a flat TODO list, a free-form context block, and simple archive entries; there is no tree model, no hierarchical relationships, and no extraction of decisions, constraints, blockers, or sub-agents.

Intent-Code Divergence

Low
Confidence
83% confidence
Finding
The module comment says it formats FOCUS.md and FOCUS-LOG.md and 'does not depend on other storage.' In practice, the script's core function is persistent storage via those filesystem files using read, write, and append operations, so the comment's phrasing is misleading about the implementation's dependence on storage.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The code hard-codes `zh-CN` and `Asia/Shanghai` for timestamp formatting, and surrounding comments/output are also Chinese-specific. This imposes a specific language/locale behavior on all users without opt-in, which matches the policy-violation category for locale constraints.

Static analysis

No suspicious patterns detected.