Back to skill

Security audit

Vibe Notion

Security checks for vulnerabilities and agentic risk

Overview

This skill is clearly for Notion automation, but it asks an agent to use a full user Notion session credential and perform broad write actions with weak safeguards.

Install only if you intentionally want an agent to act as your full Notion user through an unofficial private API. Prefer the official integration-token CLI for lower-risk work, pin and verify the package version before use, review every write/delete/archive/batch command before execution, and treat `$hints` as advisory text rather than commands to run automatically. Clear or rotate the stored Notion session token when finished.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T01 · Skill Instruction Hijacking

Error
Location
references/output-format.md:44
Finding
Untrusted CLI Response Hints Can Trigger Destructive Agent Actions<![CDATA[ ## Vulnerability Details **File Location**: `references/output-format.md:44-62` **Vulnerability Type**: Indirect instruction injection through externally supplied CLI output **Risk Level**: High ### Vulnerable Code Snippet ```markdown ## Schema Hints (`$hints`) `database get` and `database query` may include a `$hints` array when the database schema has issues. These are actionable warnings — follow the instructions in each hint to fix the problem. ```json { "id": "collection-uuid", "name": "My Database", "schema": { "Name": "title", "Status": "select" }, "$hints": [ "Rollup 'Revenue Sum' depends on deleted relation 'Deals'. This rollup will return empty values. Fix: run `database delete-property <database_id> --workspace-id <workspace_id> --property \"Revenue Sum\"` to remove it." ] } ``` **When `$hints` is present**: Read each hint carefully and execute the suggested fix commands. ``` ### Technical Analysis The Skill instructs the agent to treat the contents of the `$hints` response field as executable instructions rather than untrusted data. These hints originate from the `vibe-notion` CLI and ultimately depend on external API responses, workspace state, and the behavior of a third-party package. The documented remediation can delete database properties. No strict parser, action allowlist, argument validation, user confirmation, or separation between informational text and authorized commands is required. Consequently, a compromised dependency or manipulated hint-producing path could cause the agent to execute an attacker-selected operation. The issue is not merely that hints are displayed. The vulnerable behavior is the explicit direction to “execute the suggested fix commands,” which crosses the trust boundary between external data and agent instructions. ### Attack Path 1. An attacker compromises the CLI dependency, its response-processing logic, or another source that influences `$hints`. 2. A database query returns a `$ ...[truncated 1058 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the instruction to execute commands contained in `$hints`. 2. Treat every hint as untrusted informational text. 3. Replace free-form remediation commands with structured identifiers, such as: ```json { "code": "BROKEN_ROLLUP", "database_id": "validated-uuid", "property_id": "validated-property-id" } ``` 4. Enforce a strict allowlist of supported remediation types and validate all IDs against the current workspace and query result. 5. Never pass hint text directly to Bash, a shell parser, or another command-execution tool. 6. Display the proposed change and affected resource to the user before execution. 7. Require explicit user confirmation for deletion, archival, content replacement, schema changes, and other destructive operations. 8. Prefer read-only diagnostics by default and log the source and validation result of every remediation request. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:79
Finding
Automatic Extraction and Storage of a Full User Session Credential<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:79-89` **Vulnerability Type**: Excessive credential access and broad session authority **Risk Level**: High ### Vulnerable Code Snippet ```markdown Credentials are auto-extracted from the Notion desktop app on first use. No manual setup needed. ## Authentication Credentials (`token_v2`) are auto-extracted from the Notion desktop app when you run any command. No API keys, OAuth, or manual extraction needed. On macOS, your system may prompt for Keychain access on first use — this is normal and required to decrypt the cookie. The extracted `token_v2` is stored at `~/.config/vibe-notion/credentials.json` with `0600` permissions. ``` The authentication comparison also states: ```markdown | Auth | `token_v2` auto-extracted from Notion desktop app | `NOTION_TOKEN` env var (Integration token) | | Identity | Acts as the user | Acts as a bot | ``` ### Technical Analysis The Skill causes the third-party CLI to extract a bearer session credential from the Notion desktop application. On macOS, this may include requesting Keychain access to decrypt the cookie. The resulting `token_v2` is then persisted in a reusable JSON file. File mode `0600` appropriately limits access by other local users, but it does not mitigate the principal risks: - The token acts as the user rather than a narrowly scoped integration. - Any command may trigger extraction, including operations that could otherwise be read-only. - The third-party package receives access to the credential. - A process running as the same operating-system user can potentially read the stored token. - The private API does not provide the scope and consent controls expected from an official OAuth or integration flow. Sending the token to Notion is inherent to this Skill’s declared unofficial API functionality, and the audit found no evidence that the project intentionally sends it to an unrelated endpoint. Nevertheless, automatic acquisition and per ...[truncated 1377 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer the official Notion API with a dedicated, least-privileged integration token. 2. Require explicit, informed user approval before extracting a desktop session credential. 3. Do not trigger credential extraction automatically for every command. 4. Clearly identify the resources and privileges that the recovered session can access. 5. Keep credentials in an operating-system credential manager rather than a plaintext JSON structure, even when filesystem permissions are restrictive. 6. Minimize credential lifetime and provide explicit session-revocation and logout instructions. 7. Avoid exposing the token in debug output, logs, process arguments, error messages, or agent memory. 8. Separate read-only and write-capable workflows where technically possible. 9. Pin and verify the dependency that performs credential extraction. ]]>

T08 · Insecure Dependencies

Error
Location
SKILL.md:480
Finding
Unpinned Package Runner Can Execute a Mutable Third-Party Release<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:480-489` **Vulnerability Type**: Unpinned credential-bearing dependency execution **Risk Level**: High ### Vulnerable Code Snippet ```markdown ### `vibe-notion: command not found` The `vibe-notion` package is not installed. Run it directly using a package runner. Ask the user which one to use: ```bash npx -y vibe-notion ... bunx vibe-notion ... pnpm dlx vibe-notion ... ``` ``` The installation metadata is also unpinned: ```yaml install: - kind: node package: vibe-notion bins: [vibe-notion] ``` ### Technical Analysis The package name is specified without an exact version or integrity digest. The suggested package-runner commands can retrieve and execute the current registry release at invocation time. In particular, `npx -y` suppresses the normal interactive installation confirmation. This creates a mutable execution boundary: the code reviewed as part of the Skill is not the complete code that handles authentication and network access. A future compromised release, publisher-account takeover, registry compromise, or malicious dependency update could execute locally without corresponding changes to this repository. The risk is amplified because the package is expected to: - Extract `token_v2` from the Notion desktop application. - Access Keychain or local browser-style credential stores. - Read and write Notion workspace content. - Upload local files selected by the user. - Persist the recovered token. No evidence in the audited files proves that the current registry package is malicious. The vulnerability is the unsafe, unpinned supply-chain execution model. ### Attack Path 1. An attacker compromises the `vibe-notion` package publisher, registry entry, or transitive dependency. 2. The attacker publishes a malicious release under the expected package name. 3. The CLI is absent locally, and the agent follows the troubleshooting instructions. 4. `npx -y`, `bunx`, or `pnpm dlx` d ...[truncated 981 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the package to a specific audited version, for example `vibe-notion@1.5.0`, after verifying that version. 2. Record and verify package integrity hashes through a committed lockfile or equivalent integrity mechanism. 3. Do not use package runners that silently download the latest release in credential-bearing workflows. 4. Remove `-y` so unexpected installation requires user confirmation. 5. Verify package provenance, publisher identity, signatures, and registry metadata. 6. Review and pin transitive dependencies. 7. Install the verified artifact in a constrained environment before permitting access to credentials. 8. Restrict filesystem and network access where sandboxing is available. 9. Re-audit before upgrading to a new package version. ]]>

T02 · Agent Memory Poisoning

Warning
Location
SKILL.md:93
Finding
Persistent Workspace Metadata Can Be Poisoned Across Agent Sessions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:93-129` **Vulnerability Type**: Unvalidated persistent agent state **Risk Level**: Medium ### Vulnerable Code Snippet ```markdown ## Memory The agent maintains a `~/.config/vibe-notion/MEMORY.md` file as persistent memory across sessions. This is agent-managed — the CLI does not read or write this file. Use the `Read` and `Write` tools to manage your memory file. ### Reading Memory At the **start of every task**, read `~/.config/vibe-notion/MEMORY.md` using the `Read` tool to load any previously discovered workspace IDs, page IDs, database IDs, and user preferences. ### Writing Memory After discovering useful information, update `~/.config/vibe-notion/MEMORY.md` using the `Write` tool. Write triggers include: - After discovering workspace IDs (from `workspace list`) - After discovering useful page IDs, database IDs, collection IDs (from `search`, `page list`, `page get`, `database list`, etc.) - After the user gives you an alias or preference ("call this the Tasks DB", "my main workspace is X") - After discovering page/database structure (parent-child relationships, what databases live under which pages) ``` The stale-data handling is: ```markdown If a memorized ID returns an error (page not found, access denied), remove it from `MEMORY.md`. Don't blindly trust memorized data — verify when something seems off. ``` ### Technical Analysis The Skill mandates automatic loading of a Markdown memory file at the beginning of every task and persistence of names, aliases, identifiers, relationships, and preferences discovered from Notion. Some stored values can originate from shared or attacker-controlled workspace content, including page titles, database names, and aliases. Because the file is free-form Markdown, there is no schema boundary separating inert values from natural-language instructions. The Skill also does not require: - Escaping or normalization of stored values. - Provenance rec ...[truncated 1744 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace free-form Markdown persistence with a strict structured schema. 2. Store only validated UUIDs and length-limited display labels. 3. Escape control characters and reject labels containing instruction-like markup or command text. 4. Record provenance, workspace identity, discovery time, and verification state for every entry. 5. Scope memory by user and workspace to prevent cross-context confusion. 6. Require user consent before enabling cross-session persistence. 7. Apply restrictive permissions such as `0600` and use atomic writes. 8. Authenticate stored state with an integrity mechanism where appropriate. 9. Treat all loaded values as inert data and never as agent instructions. 10. Revalidate an identifier before write or destructive operations, not only after an error. 11. Provide a command or workflow to inspect, clear, and disable persistent memory. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Rogue AgentSelf-Modification, Session Persistence
Findings (12)

Credential Access

High
Category
Privilege Escalation
Content
Credentials (`token_v2`) are auto-extracted from the Notion desktop app when you run any command. No API keys, OAuth, or manual extraction needed.

On macOS, your system may prompt for Keychain access on first use — this is normal and required to decrypt the cookie.

The extracted `token_v2` is stored at `~/.config/vibe-notion/credentials.json` with `0600` permissions.
Confidence
93% confidence
Finding
The skill instructs that macOS Keychain access may be requested to decrypt the Notion cookie, which is credential access to a protected local secret store. In an agent skill, normalizing Keychain prompts without emphasizing sensitivity can lead users to approve extraction of a credential that grants user-level access to private Notion data.

Credential Access

High
Category
Privilege Escalation
Content
On macOS, your system may prompt for Keychain access on first use — this is normal and required to decrypt the cookie.

The extracted `token_v2` is stored at `~/.config/vibe-notion/credentials.json` with `0600` permissions.

## Memory
Confidence
95% confidence
Finding
The skill explicitly describes storing the extracted `token_v2` in `~/.config/vibe-notion/credentials.json`. Even with `0600` permissions, this is a high-value session credential for the user's Notion account; any local compromise, overbroad agent behavior, or accidental disclosure of that file could enable unauthorized access and data modification.

Session Persistence

Medium
Category
Rogue Agent
Content
If a feature you need is not supported by `vibe-notion`, let the user know and offer to file a feature request at [devxoul/vibe-notion](https://github.com/devxoul/vibe-notion/issues) on their behalf. Before submitting, strip out any real user data — IDs, names, emails, tokens, page content, or anything else that could identify the user or their workspace. Use generic placeholders instead and keep the issue focused on describing the missing capability.

## Important: Never Write Scripts

**Never write scripts (Python, TypeScript, Bash, etc.) to automate Notion operations.** The `batch` command already handles bulk operations of any size. Writing a script to loop through API calls is always wrong — use `batch` with `--file` instead.
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.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill normalizes automatic extraction of the user's `token_v2` from the desktop app and local storage of that credential, but does not present this up front as a sensitive credential-access action requiring informed consent. Because `token_v2` acts as the user against Notion's private API, compromise or misuse could expose or modify all accessible workspace content.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Content
## Authentication

Credentials (`token_v2`) are auto-extracted from the Notion desktop app when you run any command. No API keys, OAuth, or manual extraction needed.

On macOS, your system may prompt for Keychain access on first use — this is normal and required to decrypt the cookie.
Confidence
80% confidence
Finding
Skill grants unrestricted tool access without appropriate constraints. An agent with unfettered tool access can perform arbitrary actions including file modification, network requests, and code execution.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill exposes many destructive and state-changing operations such as update, archive, delete-property, add-row, and update-row without an explicit safety warning to require user confirmation before mutating data. In an agent context, this increases the chance of accidental data loss, corruption, or irreversible workspace changes from misunderstood prompts.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding
The skill recommends executing `npx -y vibe-notion` without pinning an exact package version. That causes retrieval of the latest package at runtime, creating a supply-chain risk where a compromised or malicious newly published version could execute with the user's local permissions and access Notion credentials or workspace data.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This documentation promotes high-impact batch write capabilities including create, update, archive, delete, schema changes, and file upload, but it does not prominently warn about destructive consequences, confirmation expectations, or safe-use guardrails. In an agent skill context, this increases the risk that an LLM or operator performs unintended bulk modifications at scale, especially because the feature is optimized to reduce round-trips and supports multi-step workflows.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
These examples show `page update ... --replace-content` usage without an explicit warning that the operation overwrites existing page body content. In a skill for interacting with a live Notion workspace, this can lead users or downstream agents to perform irreversible or hard-to-recover destructive edits, especially when commands are copied verbatim into automation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The dedicated 'Updating a Page' section normalizes full-content replacement as a routine update operation but does not clearly call out data-loss risk. In this context, the skill is an operational guide for a private Notion API, so omission of overwrite warnings increases the chance of accidental destructive actions against real workspace documents.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation tells users to automatically trust and execute fix commands embedded in the `$hints` output, including a destructive `database delete-property` command, without requiring independent validation, confirmation, or warning about deletion consequences. Because `$hints` is treated as actionable instruction text derived from data/API output, this creates an instruction-injection pathway where users or agents may perform schema-destructive actions based on untrusted content.

Vague Triggers

Low
Confidence
77% confidence
Finding
This markdown file includes decision-flow language that says to use `vibe-notion` whenever the desktop app is installed and even to prefer it when both authentication options are available. That guidance is broad and lacks negative examples or explicit limits on when this skill should not be invoked, which can contribute to unintended activation in loosely matching Notion-related requests.

Static analysis

No suspicious patterns detected.