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. ]]>
