Back to skill

Security audit

Notion记账财务分析

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it handles a Notion bearer token and sensitive financial records with weak scoping guidance and automatic local report persistence.

Review before installing. Use a dedicated least-privilege Notion integration shared only with the needed accounting databases, avoid putting the token directly in shell commands, and treat the generated /workspace finance report as sensitive local data that may need deletion or redaction.

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
analyze.mjs:19
Finding
Notion Integration Token Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `analyze.mjs:19`, `analyze.mjs:29-33`; documented usage in `README.md:41-44` **Vulnerability Type**: Credential exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code ```javascript const TOKEN = process.argv[2]; ``` The value is subsequently used as a bearer credential: ```javascript const HEADERS = { 'Authorization': `Bearer ${TOKEN}`, 'Notion-Version': '2025-09-03', 'Content-Type': 'application/json' }; ``` The documented invocation requires placing the secret directly on the command line: ```bash node analyze.mjs <NOTION_TOKEN> <EXPENSE_DATA_SOURCE_ID> [INCOME_DATA_SOURCE_ID] [YEAR] ``` ### Technical Analysis The script accepts the Notion Integration Token as its first command-line argument. Command-line arguments may be visible to other local processes through process-inspection facilities such as `ps` or `/proc`, subject to operating-system access controls. If a user enters the literal command in an interactive shell, the token may also be retained in shell history, terminal logs, automation logs, or command auditing systems. The token is a bearer credential: possession is sufficient to authenticate to the Notion API. Although the implementation sends it only to the official `api.notion.com` host and this network access is necessary for the declared functionality, the method used to receive the credential creates avoidable local exposure. No hidden network destination, remote payload execution, persistence, instruction hijacking, or deliberate credential exfiltration was identified. ### Attack Path 1. A user invokes the documented command with a real Notion Integration Token as the first argument. 2. While the process is running, a local attacker with sufficient process-inspection access reads the command-line arguments. Alternatively, the attacker obtains the command from shell history, terminal logging, CI logs, or command-auditing records. 3. ...[truncated 1018 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Stop accepting the token through `process.argv`. 2. Read the credential from a protected secret source, preferably: - standard input with terminal echo disabled; - a platform secret manager; or - a narrowly scoped environment variable such as `NOTION_API_TOKEN`. 3. Update the documented invocation so no literal token appears in the command: ```bash node analyze.mjs <EXPENSE_DATA_SOURCE_ID> [INCOME_DATA_SOURCE_ID] [YEAR] ``` 4. Validate that the credential exists without printing its value: ```javascript const TOKEN = process.env.NOTION_API_TOKEN; if (!TOKEN) { console.error('NOTION_API_TOKEN is required.'); process.exit(1); } ``` 5. Ensure CI systems and wrappers mask the token and never include it in command traces, debug output, or exception messages. 6. Configure the Notion integration with only the capabilities and page access necessary for accounting analysis. 7. Rotate the existing token if it has previously been supplied literally through a shell, CI command, or other logged command interface. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (12)

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The README presents the skill entirely in Chinese and the example invocation phrases are only Chinese, indicating a language-specific interaction model. There is no explicit user opt-in, alternative language option, or justification that this skill must be Chinese-only due to regional or compliance constraints.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README explicitly promotes full automatic retrieval of Notion accounting records and automatic report output to /workspace, but it does not warn that these records may contain highly sensitive financial and personal data or that generated reports may persist locally. This creates a real privacy and data-handling risk because users may provide broad-scope tokens and unintentionally expose more data than expected through local artifacts or downstream sharing.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The invocation examples include broad phrases like “生成财务报告” and “查看收支趋势,” which could appear in general conversation without clearly indicating this specific skill should run. The description does not provide negative examples or tighter constraints to distinguish when the skill should activate versus when it should not.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill asks users to provide a Notion Integration Token and financial database identifiers without warning about credential sensitivity or the privacy implications of processing personal financial records. This can lead users to expose reusable secrets and sensitive accounting data without informed consent or safe-handling guidance.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill states that it will automatically write a Markdown financial report to /workspace/ but does not warn that the file may contain highly sensitive financial information. Local artifact creation increases the risk of unintended retention, later disclosure to other tools, or accidental inclusion in logs, sync jobs, or version control.

External Transmission

Medium
Category
Data Exfiltration
Content
用户未提供 data_source_id 时,用搜索接口查找:

```bash
curl -s -X POST "https://api.notion.com/v1/search" \
  -H "Authorization: Bearer $NOTION_API_TOKEN" \
  -H "Notion-Version: 2025-09-03" \
  -d '{"query": "支出", "page_size": 20}' \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
用户未提供 data_source_id 时,用搜索接口查找:

```bash
curl -s -X POST "https://api.notion.com/v1/search" \
  -H "Authorization: Bearer $NOTION_API_TOKEN" \
  -H "Notion-Version: 2025-09-03" \
  -d '{"query": "支出", "page_size": 20}' \
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
Comments, usage text, console output, and report content are written in Chinese, and the report date formatting explicitly uses `zh-CN`. This enforces a specific language/locale experience without any opt-in or configurable language selection.

Intent-Code Divergence

Medium
Confidence
84% confidence
Finding
The file-level guidance repeatedly states that relation fields must be fully resolved by querying related pages, yet parseIncomeRecord at L154-L160 does not call the relation-resolution logic and simply accesses p.properties['收入来源']?.relation?.[0]?.title?.[0]?.plain_text. That contradicts the stated intent that relation fields require explicit lookup to obtain names.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The report section says the relation field has been '100% parsed' at L245, while the parser and resolver intentionally fall back to raw page IDs when a related page cannot be read (L107-L110, L143), and the report later warns that unresolved relation IDs may still appear (L277-L278). This is an active contradiction between the skill's documentation/output claims and its actual behavior.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script writes a financial report containing potentially sensitive personal data to a fixed path under /workspace without user confirmation or any control over persistence. In shared, synced, or agent-managed environments, this can unintentionally expose private financial information to other processes, users, or later tasks that can read the workspace.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
The natural-language instructions, examples, and trigger phrases are entirely Chinese and do not indicate whether other languages are supported. This can amount to a language/locale policy issue because the skill appears to force a specific language without user opt-in or an explicit justification.

Static analysis

No suspicious patterns detected.