Back to skill

Security audit

Notion 想法点子库 + 里程碑追踪

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real Notion integration, but it needs review because it gives broad Notion read/write guidance while handling tokens and action triggers too loosely.

Install only if you are comfortable giving an agent Notion integration access. Use a least-privilege Notion integration shared only with the intended pages or databases, replace the hardcoded database IDs with your own, avoid broad conversational triggers for writes, protect or avoid the plaintext token file, and prefer a safer HTTP client over curl arguments for bearer-token requests.

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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/notion-write-idea.py:30
Finding

Notion API Token Exposed Through Process Command-Line Arguments

Content
View full analysis
` in its process arguments. 4. A local attacker or monitoring process observes the command line while `curl` is active. 5. The attacker extracts the bearer token. 6. The attacker submits requests directly to the Notion API using the stolen token. ### Impact Assessment An attacker who obtains the token can act with the full authority of the associated Notion integration. Depending on which resources were shared with that integration, this may permit reading, creating, or modifying Notion pages and databases. It does n ...[truncated 88 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/notion-write-milestone.py:29
Finding

Notion API Token Exposed Through Milestone Script Process Arguments

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:125
Finding

Predictable Temporary File Permits Symlink Overwrite and Plaintext Data Exposure

Content
View full analysis
/tmp/idea.json << 'EOF' { "名称": "无头服务器网站登录解法", "想法摘要": "agent-browser在无头服务器无法登录需验证码网站。解法:Cookie导入、Xvfb虚拟显示器、本地登录导出session。", "决策结论": "优先试方案1(Cookie导入),最可行。", "来源": "临时想法", "相关项目": "agent-browser", "标签": ["服务器部署", "Cookie导入"], "状态": "待实现", "重要性": "中", "创建时间": "2026-04-04T22:38:00+08:00" } EOF python3 ~/.openclaw/skills/notion/scripts/notion-write-idea.py create < /tmp/idea.json ``` A similar documented milestone workflow uses `/tmp/milestone.json`. ### Technical Analysis The documented workflow creates sensitive content at a fixed, predictable path in a shared temporary directory. Shell redirection follows symbolic links. If an attacker can pre-create `/tmp/idea.json` as a symbolic link, execution of the documented command may truncate and overwrite another file writable by the victim. The file is also not deleted after use. Its effective permissions depend on the user's `umask`, which may allow other local users or processes to read the idea content. The same class of issue applies to the predictable milestone JSON path. ### Attack Path 1. An attacker with access to the shared temporary directory predicts that the victim will use `/tmp/idea.json`. 2. The attacker creates `/tmp/idea.json` as a symbolic link to a file writable by the victim, or waits to read the resulting plaintext file. 3. The victim follows the documented `cat > /tmp/idea.json` workflow. 4. Shell redirection follows the symbolic link and truncates or overwrites the linked target with JSON content. 5. Alternatively, the attacker reads the residual JSON file if its permissions allow access. 6. The file remains in `/tmp` after the Notion operation unless the user manually removes it. ### Impact Assessment The overwrite impact is limited to files writable by the user running the com ...[truncated 315 chars]
Remediation
View remediation
"$idea_file" <<'EOF' { "properties": {} } EOF python3 ~/.openclaw/skills/notion/scripts/notion-write-idea.py create < "$idea_file" ``` - Apply the same hardening to the documented milestone workflow. - Redesign confirmation input separately from the JSON input stream, because the scripts currently consume all standard input with `sys.stdin.read()` before attempting to call `input()`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
Findings (34)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The declared description presents a broad Notion API capability for creating and managing pages, databases, and blocks, plus an idea-persistence workflow. The supplied code only implements a specialized write script for idea storage: it can create or update pages in one fixed database, with manual confirmation, and does not handle databases or blocks at all. There is no implementation of the stated natural-language triggers; instead it is a command-line tool expecting JSON on stdin. While the idea-persistence aspect is consistent, the broader declared functionality materially overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The declared description presents a broad Notion integration for creating and managing pages, databases, and blocks, plus a persistent idea-library workflow triggered by specific user phrases. The supplied code instead implements a single-purpose command-line script for creating or updating milestone records in one hardcoded Notion database. It reads JSON from stdin, displays fields, asks the user to confirm with y/Y, and then writes via the Notion API using a local API key. There is no handling of blocks, no database management, no general page-management abstraction beyond posting/updating a page in one database, and no trigger detection or idea-persistence workflow corresponding to the described “想法点子库(💡)持久化” behavior. This is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill exposes shell-based capabilities and includes executable curl/python command patterns but declares no explicit tool scope or permission boundary. That omission increases the risk that an agent can invoke networked shell actions without clear policy constraints or user visibility, especially because the skill handles authenticated API operations.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The setup stores a long-lived Notion API key in a predictable plaintext file under the user's home directory. Plaintext credential persistence increases the chance of token theft through local compromise, accidental exposure, backups, or other skills reading the file.

Content

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

Setup

bash
mkdir -p ~/.config/notion
echo "ntn_your_key_here" > ~/.config/notion/api_key

Integration API key starts with ntn_ or secret_. Share target pages/databases with your integration (click "..." → "Connect to" → your integration name).

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The documented endpoint use confirms that the skill is designed for outbound network communication to a third-party service using bearer authentication. In the presence of shell access and missing explicit tool scope, this broadens the risk of exfiltration or unintended disclosure through otherwise routine API calls.

Content

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

md
NOTION_KEY=$(cat ~/.config/notion/api_key)

# Search
curl -s -X POST "https://api.notion.com/v1/search" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The documented endpoint use confirms that the skill is designed for outbound network communication to a third-party service using bearer authentication. In the presence of shell access and missing explicit tool scope, this broadens the risk of exfiltration or unintended disclosure through otherwise routine API calls.

Content

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

md
NOTION_KEY=$(cat ~/.config/notion/api_key)

# Search
curl -s -X POST "https://api.notion.com/v1/search" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

Reading pages from Notion is an external data retrieval action that can expose sensitive workspace contents through the agent environment or downstream processing. The risk is contextual rather than inherently malicious, but it remains a true security concern because authenticated content leaves Notion's UI boundary and enters shell/agent outputs.

Content

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

md
-d '{"query": "keywords"}'

# Get page
curl -s "https://api.notion.com/v1/pages/{page_id}" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03"

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

Querying a data source sends authenticated requests and returns structured workspace content, making the skill capable of bulk data access. That increases the blast radius compared with single-page reads, especially if an agent is induced to enumerate or export large portions of the workspace.

Content

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

md
-H "Notion-Version: 2025-09-03"

# Query database (newer endpoint, use data_source_id)
curl -s -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

Creating pages transmits user-provided content to an external service and modifies persistent state under bearer-token authority. If triggered accidentally or through prompt manipulation, it can create unauthorized records or leak sensitive conversational content into a long-lived external store.

Content

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

md
-d '{"sorts": [{"property": "创建时间", "direction": "descending"}], "page_size": 20}'

# Create page (use database_id as parent, version 2022-06-28)
curl -s -X POST "https://api.notion.com/v1/pages" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2022-06-28" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

Updating page properties is an authenticated outbound write that can alter records in Notion. In combination with the ambiguous status triggers in this skill, this becomes more dangerous because ordinary conversation may result in persistent external state changes.

Content

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

md
-d '{"parent": {"database_id": "xxx"}, "properties": {"Name": {"title": [{"text": {"content": "Title"}}]}}}'

# Update page properties
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2022-06-28" \
  -H "Content-Type: application/json" \

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
1. 从消息提取:时间戳 → 标题(≤20字) → 摘要 → 决策结论 → 来源/状态/重要性
2. 组装 JSON(见下方模板)
3. **调用确认脚本**:`python3 ~/.openclaw/skills/notion/scripts/notion-write-idea.py create < idea.json`
4. 脚本展示内容 → 用户输入 `y` 确认 → 才写入 Notion
5. 写入后脚本自动验证并返回 Notion 页面链接

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
1. 从消息提取:时间戳 → 标题(≤20字) → 摘要 → 决策结论 → 来源/状态/重要性
2. 组装 JSON(见下方模板)
3. **调用确认脚本**:`python3 ~/.openclaw/skills/notion/scripts/notion-write-idea.py create < idea.json`
4. 脚本展示内容 → 用户输入 `y` 确认 → 才写入 Notion
5. 写入后脚本自动验证并返回 Notion 页面链接

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The planning trigger phrase set includes overly broad natural-language expressions, which can be matched during ordinary conversation and cause unintended state transitions or writes. In a skill that persists content to Notion, ambiguous activation can lead to unauthorized or accidental modification of records based only on conversational wording.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The status-update triggers are short, common phrases that may appear in normal discussion and are not scoped to a specific record, action context, or confirmation workflow. That makes accidental or adversarial prompt-induced updates more likely, especially for destructive transitions like archive or completion states.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

This instance again demonstrates authenticated transmission to a specific hardcoded data source, which materially increases confidentiality risk if the skill is reused outside its original trusted context. Hardcoded internal IDs also reveal structural metadata about the owner's workspace.

Content

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

查询所有想法(按时间倒序)

bash
curl -s -X POST "https://api.notion.com/v1/data_sources/339d8e39-9e68-814b-8fc9-c06adfb3ae00/query" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

This instance again demonstrates authenticated transmission to a specific hardcoded data source, which materially increases confidentiality risk if the skill is reused outside its original trusted context. Hardcoded internal IDs also reveal structural metadata about the owner's workspace.

Content

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

查询所有想法(按时间倒序)

bash
curl -s -X POST "https://api.notion.com/v1/data_sources/339d8e39-9e68-814b-8fc9-c06adfb3ae00/query" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The milestone query enables traversal of relationships between ideas and milestones, potentially exposing linked project history and internal URLs. Because it filters on a page ID, an attacker or confused agent with a valid ID can pivot into related records and enumerate associated data.

Content

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

查询某想法的里程碑

bash
curl -s -X POST "https://api.notion.com/v1/data_sources/339d8e39-9e68-8130-932c-ecf46af154b5/query" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

Search is a broad data-discovery primitive that can reveal names, pages, and data sources across the shared integration scope. In an agent context, search is especially sensitive because it can be used to discover assets for later exfiltration or modification.

Content

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

Search pages and data sources

bash
curl -s -X POST "https://api.notion.com/v1/search" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This read operation fetches full page data from Notion into the local execution context, where it may be logged, summarized, or further transmitted. The external read is legitimate for the feature set, but still represents a real confidentiality boundary crossing.

Content

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

Get page

bash
curl -s "https://api.notion.com/v1/pages/{page_id}" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03"

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

Fetching page blocks can retrieve large amounts of rich content, comments, or embedded data from a workspace page. That makes it a meaningful exfiltration surface if invoked broadly or on sensitive pages.

Content

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

Get page blocks

bash
curl -s "https://api.notion.com/v1/blocks/{page_id}/children" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03"

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

Creating databases is a privileged external write capability that can alter workspace structure, not just content. Structural writes raise integrity risk because an induced agent action could create clutter, misleading schemas, or shadow stores for later data capture.

Content

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

Create database

bash
curl -s -X POST "https://api.notion.com/v1/databases" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2022-06-28" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

Adding blocks to a page performs authenticated external modification of page contents. In a prompt-injection or accidental-trigger scenario, this can persist unauthorized text, links, or instructions into trusted workspace documents.

Content

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

Add blocks to page

bash
curl -s -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

The helper function centralizes arbitrary outbound Notion API requests using a locally stored bearer token, making it easy to extend into broad read/write access with minimal guardrails. Because it accepts a free-form endpoint parameter, it increases the risk of unintended or overbroad authenticated requests from agent-controlled inputs.

Content

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

md
def notion_req(method, endpoint, body=None, version="2025-09-03"):
    key = open("/root/.config/notion/api_key").read().strip()
    cmd = ["curl", "-s", "-X", method,
           f"https://api.notion.com/v1/{endpoint}",
           "-H", f"Authorization: Bearer {key}",
           "-H", f"Notion-Version: {version}",
           "-H", "Content-Type: application/json"]

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/notion-write-idea.py (reported line 6)May include surrounding context.

python
notion-write-idea.py — 想法入库写入脚本(带用户确认)

用法:
  python3 notion-write-idea.py create < JSON   # 从 stdin 读取 JSON
  python3 notion-write-idea.py update <JSON>   # 更新页面

确认流程:

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/notion-write-idea.py (reported line 6)May include surrounding context.

python
notion-write-idea.py — 想法入库写入脚本(带用户确认)

用法:
  python3 notion-write-idea.py create < JSON   # 从 stdin 读取 JSON
  python3 notion-write-idea.py update <JSON>   # 更新页面

确认流程:

Static analysis

No suspicious patterns detected.