Back to skill

Security audit

Notion Sync

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real Notion sync tool, but it needs review because it can upload unintended local files or secrets and stores the Notion token plainly.

Install only if you are comfortable sending the chosen directory's file contents and structure to Notion. Before syncing, run dry-run, use a narrow directory, add explicit ignores for secrets such as .env files, credentials, keys, and private configs, avoid syncing untrusted repositories with symlinks, and treat .notion-sync.json as a sensitive file because it contains the Notion token.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
src/sync.ts:12
Finding

Ignored secrets may be uploaded because .gitignore is not applied

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/config.ts:18
Finding

Notion API token is exposed through command-line arguments and plaintext configuration

Content
View full analysis
', 'Notion API token (ntn_...)') .requiredOption('--page ', 'Root Notion page ID to sync into') .option('--dir ', 'Directory to sync (default: current dir)', process.cwd()) .action(({ token, page, dir }) => { ``` ```typescript export function saveConfig(dir: string, config: NotionSyncConfig): void { const file = path.join(dir, CONFIG_FILE); fs.writeFileSync(file, JSON.stringify(config, null, 2)); } ``` ```typescript export function initConfig(dir: string, token: string, rootPageId: string): NotionSyncConfig { const config: NotionSyncConfig = { path: dir, notion: { token, rootPageId }, ignore: ['node_modules', '.git', 'dist', '.notion-sync.json', '*.lock', '*.log'], checksums: {} }; saveConfig(dir, config); return config; } ``` Documented invocation: ```bash notion-sync init --token ntn_xxx --page [--dir ] ``` ### Technical Analysis The CLI requires the Notion integration token as a command-line argument. Command-line secrets can be retained in shell history and, depending on the operating system and process visibility settings, may be observable in process listings while the command executes. The token is subsequently serialized directly into `.notion-sync.json`. `fs.writeFileSync` is called without an explicit restrictive file mode, so protection depends on the user's umask and existing file permissions. No OS credential store, encrypted secret storage, or environment-based token reference is used. ### Attack Path 1. A user runs the documented initialization command with a valid No ...[truncated 914 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/sync.ts:19
Finding

Symbolic links can disclose files outside the configured synchronization root

Content
View full analysis
, base = dir): string[] { const entries = fs.readdirSync(dir, { withFileTypes: true }); const files: string[] = []; for (const entry of entries) { const rel = path.relative(base, path.join(dir, entry.name)); if (ig.ignores(rel)) continue; if (entry.isDirectory()) { files.push(...getFiles(path.join(dir, entry.name), ig, base)); } else { files.push(rel); } } return files; } ``` ```typescript const absPath = path.join(config.path, relPath); let content: string; try { content = fs.readFileSync(absPath, 'utf8'); } catch { errors.push(`Cannot read: ${relPath}`); continue; } ``` ### Technical Analysis Directory entries are classified with `entry.isDirectory()`. A symbolic link is not treated as a directory by this check and therefore enters the file branch. Later, `fs.readFileSync` follows the symbolic link automatically. The code does not use `lstat` to reject links, resolve the candidate path with `realpath`, or verify that the resolved target remains inside the canonical synchronization root. As a result, a link located inside the workspace can reference any file readable by the current process, even when the target is outside the directory selected by the user. ### Attack Path 1. An attacker contributes a repository or archive containing a symbolic link, for example: `report.txt -> /home/user/.ssh/id_rsa` 2. The user initializes and synchronizes that repository. 3. `getFiles` treats `report.txt` as a regular synchronization candidate. 4. `path.join` produces a path lexically inside the workspace, but no canonical containment validation occurs. 5. `readFileSync` follows the link and reads the external target. 6. The targe ...[truncated 642 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (27)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

notion-sync sync --dir /some/path # sync a specific directory notion-sync status # show sync state notion-sync ignore list # list ignore patterns notion-sync ignore add "*.env" # add ignore pattern

text

### Default Ignore Patterns

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

notion-sync sync --dir /some/path # sync a specific directory notion-sync status # show sync state notion-sync ignore list # list ignore patterns notion-sync ignore add "*.env" # add ignore pattern

text

### Default Ignore Patterns

Known Vulnerable Dependency: brace-expansion==2.0.2 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
89% confidence
Finding

The lockfile pins brace-expansion 2.0.2, which is reported vulnerable to denial-of-service conditions from pathological brace patterns. In this package it is only a transitive dependency via glob/minimatch, so exploitability depends on whether untrusted glob-like patterns are accepted at runtime, but the dependency risk is real.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
80% confidence
Finding

form-data 4.0.5 is a real vulnerable dependency according to the advisory, with CRLF injection risk when multipart field names or filenames are attacker-controlled. Here it is transitive under the Notion client stack, so impact depends on whether this skill passes untrusted names into multipart uploads, but the dependency weakness itself is genuine.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: js-yaml==3.14.2 — 4 advisory(ies): CVE-2026-84375 (js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources); CVE-2026-59869 (js-yaml: YAML merge-key chains can force quadratic CPU consumption); GHSA-5p4m-2wfm-xmqj (JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026) +1 more

High
Category
Supply Chain
Confidence
92% confidence
Finding

js-yaml 3.14.2 has multiple reported CPU-exhaustion issues during parsing of crafted YAML. Because this skill includes gray-matter and likely processes front matter from local files being synced, malicious or malformed Markdown/YAML content could trigger denial of service during parsing.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: minimatch==9.0.5 — 3 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu); CVE-2026-26996 (minimatch has a ReDoS via repeated wildcards with non-matching literal in patter); CVE-2026-27903 (minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja)

High
Category
Supply Chain
Confidence
86% confidence
Finding

minimatch 9.0.5 is flagged for ReDoS-style backtracking on crafted patterns. This skill's purpose includes syncing directories and managing ignore patterns, which makes attacker- or user-controlled glob patterns more likely than in a generic package and increases practical risk of CPU exhaustion.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: picomatch==4.0.3 — 2 advisory(ies): CVE-2026-33672 (Picomatch: Method Injection in POSIX Character Classes causes incorrect Glob Mat); CVE-2026-33671 (Picomatch has a ReDoS vulnerability via extglob quantifiers)

High
Category
Supply Chain
Confidence
85% confidence
Finding

picomatch 4.0.3 is reported vulnerable to method-injection and ReDoS issues in crafted glob expressions. Although it appears in dev tooling here, if any build or local automation paths process untrusted patterns, this can still cause incorrect matching or denial of service; however, this is less directly dangerous to end users than runtime deps.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: rollup==4.58.0 — 1 advisory(ies): CVE-2026-27606 (Rollup 4 has Arbitrary File Write via Path Traversal)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README promotes syncing arbitrary workspace directories and file contents to Notion but does not clearly warn that project data will be transmitted to a third-party SaaS. In this skill context, that omission is meaningful because users may run it from sensitive repositories and unintentionally exfiltrate source code, secrets, internal docs, or regulated data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation instructs users to pass the Notion API token directly on the command line, which can leak credentials via shell history, terminal logging, CI logs, or process inspection by other local users. Because this skill is specifically about authenticating to a third-party API, exposing the token can enable unauthorized access to the connected Notion workspace.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill is explicitly designed to sync local files and directories to Notion, a third-party service, but it does not warn users that file contents and directory structure may be transmitted externally. In a workspace automation context, users may invoke this on sensitive repositories or documents and unintentionally exfiltrate proprietary or confidential data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The initialization example passes the Notion token directly on the command line, which can expose credentials via shell history, process listings, logs, or terminal recordings. This is especially risky in shared development environments, CI systems, or when users copy commands into monitored shells.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The package description advertises syncing 'any workspace or directory' to Notion, which is a broad trigger scope for an agent skill that can exfiltrate local content to a third-party service. In an agent context, overly broad scope increases the chance of accidental oversharing of sensitive files because users are not warned that the operation may recursively include large portions of the workspace.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest describes local-to-Notion syncing without warning that local workspace contents may be transmitted to a remote third-party service. This omission is risky for agent-driven use because users may interpret the action as a local formatting or indexing task rather than outbound data transfer, leading to unintended disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The config initialization path stores the Notion API token directly in .notion-sync.json via saveConfig without any warning, masking, or safer secret-handling mechanism. Because this file is created inside the workspace and only excluded by convention, the token can be exposed through accidental commits, backups, file sharing, or other local tooling that reads project files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This function reads arbitrary workspace files and uploads their full contents to Notion, but the code shown provides no in-flow confirmation, disclosure, scope preview, or guardrail before transmitting data to an external SaaS. In a sync skill, that behavior is expected, but it is still risky because users may unintentionally sync secrets, private notes, config files, or other sensitive content if ignore patterns are incomplete or misconfigured.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: esbuild==0.27.3 — 1 advisory(ies): GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)

Low
Category
Supply Chain
Confidence
60% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 34)May include surrounding context.

json
"node": ">=18"
  },
  "dependencies": {
    "@notionhq/client": "^2.2.15",
    "chalk": "^5.3.0",
    "commander": "^12.0.0",
    "glob": "^10.3.10",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 35)May include surrounding context.

json
},
  "dependencies": {
    "@notionhq/client": "^2.2.15",
    "chalk": "^5.3.0",
    "commander": "^12.0.0",
    "glob": "^10.3.10",
    "gray-matter": "^4.0.3",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 36)May include surrounding context.

json
"dependencies": {
    "@notionhq/client": "^2.2.15",
    "chalk": "^5.3.0",
    "commander": "^12.0.0",
    "glob": "^10.3.10",
    "gray-matter": "^4.0.3",
    "ignore": "^5.3.0"

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 37)May include surrounding context.

json
"@notionhq/client": "^2.2.15",
    "chalk": "^5.3.0",
    "commander": "^12.0.0",
    "glob": "^10.3.10",
    "gray-matter": "^4.0.3",
    "ignore": "^5.3.0"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 38)May include surrounding context.

json
"chalk": "^5.3.0",
    "commander": "^12.0.0",
    "glob": "^10.3.10",
    "gray-matter": "^4.0.3",
    "ignore": "^5.3.0"
  },
  "devDependencies": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 39)May include surrounding context.

json
"commander": "^12.0.0",
    "glob": "^10.3.10",
    "gray-matter": "^4.0.3",
    "ignore": "^5.3.0"
  },
  "devDependencies": {
    "@types/node": "^20.11.0",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 42)May include surrounding context.

json
"ignore": "^5.3.0"
  },
  "devDependencies": {
    "@types/node": "^20.11.0",
    "tsup": "^8.0.1",
    "typescript": "^5.3.3"
  }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 43)May include surrounding context.

json
},
  "devDependencies": {
    "@types/node": "^20.11.0",
    "tsup": "^8.0.1",
    "typescript": "^5.3.3"
  }
}

Static analysis

No suspicious patterns detected.