T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:54
- Finding
- Path Traversal Through Unvalidated Notion Profile Name## Vulnerability Details **File Location**: `SKILL.md`, lines 54-66 and 76-81 **Vulnerability Type**: Path traversal leading to unintended local-file disclosure **Risk Level**: Medium The Skill constructs a credential-file path using the unvalidated `NOTION_PROFILE` environment variable: ```bash mkdir -p ~/.config/notion echo "ntn_personal_key" > ~/.config/notion/personal.key echo "ntn_work_key" > ~/.config/notion/work.key chmod 600 ~/.config/notion/*.key ``` ```bash NOTION_PROFILE="${NOTION_PROFILE:-personal}" NOTION_KEY="${NOTION_API_KEY:-$(cat ~/.config/notion/${NOTION_PROFILE}.key 2>/dev/null)}" [ -n "$NOTION_KEY" ] || echo "No Notion key for profile '$NOTION_PROFILE'" ``` The resulting file contents are subsequently included in an outbound HTTP Authorization header: ```bash notion() { local method="$1" path="$2"; shift 2 curl -sS -X "$method" "https://api.notion.com/v1${path}" \ -H "Authorization: Bearer $NOTION_KEY" \ -H "Notion-Version: 2025-09-03" \ -H "Content-Type: application/json" "$@" } ``` ### Technical Analysis `NOTION_PROFILE` is directly interpolated into the path `~/.config/notion/${NOTION_PROFILE}.key` without an allowlist, character validation, or canonical-path containment check. A value containing `../` components can escape the intended Notion configuration directory. The fixed `.key` suffix restricts the immediately reachable targets to paths whose resulting names end in `.key`, but it does not guarantee that the selected file is a configured Notion profile or that it remains under `~/.config/notion`. If `NOTION_API_KEY` is unset, the contents of the selected file are assigned to `NOTION_KEY`. The `notion` helper then sends `NOTION_KEY` to the official Notion API over HTTPS as a bearer token. Sending a valid Notion token to this endpoint is necessary for the declared functionality. However, allowing an unvalidated profile selector to source arb ...[truncated 1653 chars]
- Remediation
- ## Remediation Suggestions Restrict profile selection to explicitly supported names: ```bash NOTION_PROFILE="${NOTION_PROFILE:-personal}" case "$NOTION_PROFILE" in personal|work) ;; *) echo "Invalid Notion profile" >&2 return 1 ;; esac key_file="$HOME/.config/notion/$NOTION_PROFILE.key" NOTION_KEY="${NOTION_API_KEY:-$(cat "$key_file" 2>/dev/null)}" if [ -z "$NOTION_KEY" ]; then echo "No Notion key for profile '$NOTION_PROFILE'" >&2 return 1 fi ``` If arbitrary user-defined profile names are required: 1. Permit only a narrow format such as `^[A-Za-z0-9_-]+$`. 2. Reject profile names containing path separators, traversal components, whitespace, or shell metacharacters. 3. Resolve the key file to a canonical path and verify that it remains beneath `$HOME/.config/notion/`. 4. Require the key file to be a regular file owned by the expected user and not writable by other users. 5. Validate that the loaded value has an expected Notion token prefix, such as `ntn_` or the documented legacy `secret_`, before using it as an Authorization header. 6. Terminate immediately when the profile is invalid or the token is absent rather than merely printing an error and permitting later requests. 7. Continue using HTTPS and avoid printing, logging, or embedding the token in command diagnostics.
