Back to skill

Security audit

Second Brain Triage

Security checks for vulnerabilities and agentic risk

Overview

This is a local note-triage utility with no hidden network, credential, or persistence behavior, though CSV export should be used carefully with untrusted content.

Install only if you want a local text/notes triage helper. Prefer JSON or Markdown exports for untrusted notes, avoid opening generated CSV files from untrusted input in spreadsheet software unless the CSV escaping is fixed, and expect primarily Chinese-language output.

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
src/index.js:278
Finding
CSV Formula Injection in Library Report Export<![CDATA[ ## Vulnerability Details **File Location**: `src/index.js:278-294` **Vulnerability Type**: CSV formula injection and improper CSV escaping **Risk Level**: Medium ### Vulnerable Code ```javascript _exportCsv(results) { const headers = ['标题', '类型', '分类', '紧急度', '置信度', '标签', '建议']; const lines = [headers.join(',')]; for (const result of results) { const s = result.summary; const row = [ `"${s.title}"`, s.type, s.category, s.urgencyScore, result.classification.confidence.toFixed(2), `"${s.keyTags.join(';')}"`, `"${s.action}"`, ]; lines.push(row.join(',')); } return lines.join('\n'); } ``` ### Technical Analysis The CSV exporter writes `s.title` directly into a quoted CSV cell. The title originates from user-controlled content: the content analyzer uses the first nonempty input line as the title. CSV quoting does not prevent spreadsheet applications from interpreting a cell beginning with `=`, `+`, `-`, or `@` as a formula. For example, an input title containing a formula such as `=HYPERLINK("https://attacker.example/collect","Open")` remains a formula when the exported report is opened in compatible spreadsheet software. Depending on the spreadsheet client and its security configuration, more dangerous formulas or legacy external-command mechanisms may be available. The implementation also fails to escape embedded double quotes by replacing `"` with `""`. An attacker can therefore produce malformed CSV structure and potentially alter how subsequent content is interpreted. ### Attack Path 1. An attacker supplies a note or batch item whose first nonempty line begins with a spreadsheet formula. 2. `ContentAnalyzer` stores that line in `metadata.title`. 3. `_generateSummary` propagates the value to `summary.title`. 4. A user calls `exportReport(results, 'csv')`. 5. `_exportCsv` places the title into the CSV without formula neutralization or proper quote escaping. 6. The victim opens ...[truncated 1015 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Create a single CSV-escaping function and apply it to every exported string cell. The function should: 1. Convert null and undefined values safely. 2. Prefix values beginning with `=`, `+`, `-`, `@`, tab, or carriage return with an apostrophe. 3. Escape every embedded double quote as two double quotes. 4. Wrap the resulting value in double quotes. 5. Be shared by the library and CLI exporters to prevent inconsistent fixes. Example: ```javascript function escapeCsv(value) { let text = String(value ?? ''); if (/^[=+\-@\t\r]/.test(text)) { text = `'${text}`; } return `"${text.replace(/"/g, '""')}"`; } ``` Use it consistently: ```javascript const row = [ escapeCsv(s.title), escapeCsv(s.type), escapeCsv(s.category), s.urgencyScore, result.classification.confidence.toFixed(2), escapeCsv(s.keyTags.join(';')), escapeCsv(s.action), ]; ``` Add regression tests covering: - Titles beginning with each recognized formula prefix. - Titles containing commas. - Titles containing double quotes. - Titles containing carriage returns or line breaks. - Normal Unicode and ASCII titles. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/triage.js:183
Finding
CSV Formula Injection in CLI Report Export<![CDATA[ ## Vulnerability Details **File Location**: `scripts/triage.js:183-202` **Vulnerability Type**: CSV formula injection and improper CSV escaping **Risk Level**: Medium ### Vulnerable Code ```javascript function formatAsCsv(result) { const headers = ['标题', '类型', '分类', '紧急度', '置信度', '标签', '建议']; const lines = [headers.join(',')]; const items = Array.isArray(result) ? result : [result]; for (const item of items) { const s = item.summary; const row = [ `"${s.title}"`, s.type, s.category, s.urgencyScore, item.classification.confidence.toFixed(2), `"${s.keyTags.join(';')}"`, `"${s.action}"`, ]; lines.push(row.join(',')); } return lines.join('\n'); } ``` ### Technical Analysis The CLI independently implements the same unsafe CSV serialization behavior as the library exporter. Attacker-controlled titles are wrapped in double quotes but are not neutralized before being written to the report. Spreadsheet programs generally continue to evaluate quoted CSV cells as formulas when their values begin with formula-control characters. Consequently, quoting alone does not make values such as `=HYPERLINK(...)` safe. Embedded double quotes are also written without CSV escaping, permitting malformed output and ambiguous cell parsing. The CLI accepts attacker-controlled data through all of the following interfaces: - A direct positional content argument. - A text file supplied using `--file`. - A JSON array supplied using `--batch`. The output can then be saved as CSV through `--format csv --output <path>`. ### Attack Path 1. An attacker prepares content whose first nonempty line is a spreadsheet formula. 2. The victim passes that content directly to the CLI or processes an attacker-supplied text or batch JSON file. 3. The content analyzer promotes the first line to the exported title. 4. The victim requests CSV output, for example: ```bash node scripts/triage.js --batch items.js ...[truncated 1079 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Remove the duplicate ad hoc CSV serializer and reuse a hardened CSV export implementation from the main library. Centralizing serialization prevents one export path from remaining vulnerable after the other is corrected. At minimum: 1. Neutralize formula prefixes including `=`, `+`, `-`, `@`, tab, and carriage return. 2. Escape embedded double quotes according to RFC 4180. 3. Quote all string fields. 4. Validate the requested output format against an explicit allowlist. 5. Add CLI integration tests that generate a CSV from malicious direct, file, and batch input. A shared helper can use the following pattern: ```javascript function escapeCsv(value) { let text = String(value ?? ''); if (/^[=+\-@\t\r]/.test(text)) { text = `'${text}`; } return `"${text.replace(/"/g, '""')}"`; } ``` Prefer invoking the library's corrected exporter instead of maintaining a second implementation: ```javascript const output = Array.isArray(result) ? triage.exportReport(result, options.format) : formatResult(result, options.format); ``` If single-item exports require separate handling, ensure both paths call the same `escapeCsv` function. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description promises a PARA-based triage and categorization system for organizing notes and knowledge bases. However, this code does not implement PARA concepts or map content into Projects, Areas, Resources, or Archive. Instead, it performs generic content analysis: URL detection, content-type classification, task/code/email/article heuristics, and metadata extraction such as tags, dates, domain, and simple task priority parsing. While some extracted fields could support a larger organizer, this chunk's actual purpose is materially different from the declared PARA triage system.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The code chunk does not implement the declared PARA-based triage system. It never assigns items to Projects, Areas, Resources, or Archive, and it contains no scoring model for priority. Instead, its core purpose is detecting relationships among items via lexical/tag/semantic similarity, grouping related content, suggesting merges/links/tags, identifying topic clusters, and finding duplicates. While relatedness detection could support note organization as a secondary feature, the declared primary behavior and the implemented primary behavior are materially different.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description emphasizes PARA-based organization and automatic categorization of notes/content within a second-brain system. However, this code chunk does not implement PARA classification logic at all. Its core function is to score urgency using keyword matching, date parsing, contextual signals, and metadata, then generate recommendations and sort items by urgency. Priority scoring is mentioned in the description, but the stated primary framing is a PARA triage/categorization system; this code is a standalone urgency scorer with no Projects/Areas/Resources/Archive behavior. That is a material description-behavior mismatch.

Ae1

High
Category
analysis-evasion
Content
node scripts/triage.js "Text content to process"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/triage.js "Text content to process"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/triage.js "Text content to process"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The primary skill description is written in Chinese and the README provides no indication that other languages are supported or that the Chinese-only presentation is an intentional, region-specific constraint. This can violate a language/locale policy when users are not given an explicit language choice or opt-in.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The description says to use the skill whenever the user wants to organize notes, classify content, prioritize tasks, or manage a second brain, which is broad enough to trigger in many ordinary productivity conversations. Over-broad activation increases the chance the skill is invoked on unrelated or sensitive user content, creating unnecessary data exposure and potentially bypassing more appropriate, narrower skills.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
Natural-language text in the banner, options, and examples forces a specific language for user interaction, which can violate language/locale policy when no opt-in or alternative is provided. The file does not indicate that this is a region-specific tool or give users a way to select another language.

Natural-Language Policy Violations

Medium
Confidence
83% confidence
Finding
The file’s natural-language descriptions and comments are predominantly in Chinese, and the logic includes Chinese-specific content categories and patterns throughout the implementation. There is no visible indication that language handling is optional, user-selectable, or justified as a region-specific tool, which can conflict with a language/locale policy requiring user choice or documented constraints.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The file-level description and all user-facing strings are written in Chinese, including report headers, labels, and error text. There is no indication that users can choose another language or that the locale restriction is intentional and documented, which may violate a language/locale choice policy.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The class header and surrounding descriptive comments present the skill description in Chinese, and the classifier logic is heavily built around Chinese-language keywords and patterns alongside some English terms. There is no natural-language indication that language choice is optional or that the skill is intentionally limited to a Chinese-speaking context, which can violate a language/locale policy requiring user choice or explicit justification.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
This code embeds user-facing descriptions and recommendation labels primarily in Chinese, including the module description and urgency labels, without indicating that language is configurable or chosen by the user. That creates a natural-language locale policy concern because the skill effectively enforces a specific language experience by default.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The returned recommendation and action-window strings are presented only in Chinese, and there is no visible option for callers or users to request another language. This is a policy-relevant locale constraint because the skill imposes a single language on end users without opt-in.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
The file introduces a Chinese-language scenario and output expectations after predominantly English instructions, but does not explain how language is chosen or whether responses should match user language. This can create an implicit locale policy inconsistency rather than an explicit user opt-in or documented multilingual behavior.

Missing User Warnings

Low
Confidence
81% confidence
Finding
This code performs a file write when `--output` is supplied, but the user-facing help only lists the option and does not disclose that the file will be written directly, potentially overwriting existing content. For SQP-2 on code files, file writes should have some visible disclosure such as a warning in help text, comment, or confirmation prompt unless clearly covered by the skill description.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The file-level description and most comments are written in Chinese, while some identifiers and embedded terms are in English. Because the skill does not state that it is region-specific or provide any language/locale opt-in, this can be read as imposing a language choice on users or maintainers.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
Multiple test cases and string literals are written in Chinese, including titles, descriptions, and task text, but the file does not indicate that the skill is intentionally limited to Chinese input or that users can choose another language. Under the policy for natural-language violations, forcing or assuming a specific language without opt-in can be a locale-policy issue.

Static analysis

No suspicious patterns detected.