T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/clip.js:88
- Finding
- Windows Shell Command Injection Through Untrusted Clipped Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/clip.js`, lines 88-97 **Vulnerability Type**: OS command injection **Risk Level**: High ```js function postToFlomo(content, tags) { const tagStr = tags.map(t => `#${t}`).join(' '); const body = JSON.stringify({ content: tagStr ? `${tagStr}\n\n${content}` : content }); try { const result = execSync( `curl.exe --noproxy "*" -s -X POST "${FLOMO_WEBHOOK}" -H "Content-Type: application/json" -d ${JSON.stringify(body).replace(/"/g, '\\"')}`, { encoding: 'utf8', timeout: 15000 } ); ``` ### Technical Analysis The function builds an operating-system command by directly interpolating the Flomo webhook URL and a JSON body containing clipped content and user-supplied tags. The resulting string is passed to `execSync`, which executes it through a shell. Replacing double quotes with `\"` does not safely escape data for Windows `cmd.exe`. Shell metacharacters such as `&`, `|`, `>`, `<`, `^`, and environment-variable expansion through `%...%` may retain special meaning depending on the final quoting context. The content originates from a remote webpage, while tags and `FLOMO_WEBHOOK` can also be supplied externally. Consequently, attacker-controlled input crosses directly from an untrusted source into a shell command. The later HTTPS fallback does not mitigate the issue because it is only reached after the initial command has already been executed or has failed. ### Attack Path 1. An attacker creates or compromises a webpage containing text with Windows shell metacharacters and a command payload. 2. The attacker persuades a user or Agent to clip that URL using the default Flomo target. 3. `fetch()` downloads the page and `extractText()` places the attacker-controlled text in `content`. 4. `main()` includes that text in `clipContent` and passes it to `postToFlomo()`. 5. `postToFlomo()` serializes the content into `body` and interpolates it into the `curl.exe` command string. 6. `ex ...[truncated 675 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Remove the `execSync` delivery path and use Node.js `https.request()` or the built-in `fetch()` API for every platform. - Do not invoke a command shell to transmit HTTP data. - If an external executable is strictly required, use `execFile()` or `spawn()` with: - A fixed executable path. - An argument array rather than a concatenated command string. - `shell: false`. - Strict validation of the webhook URL. - Restrict webhook destinations to HTTPS and, where appropriate, an allowlist of expected hosts. - Treat downloaded webpage content, tags, and environment variables as untrusted data. - Add regression tests containing Windows shell metacharacters to verify that they are transmitted only as data. ]]>
