├── README.md ├── linux-poc ├── .vscode │ └── settings.json ├── package.json └── payload.sh └── windows-poc ├── .vscode └── settings.json └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # RCE in NPM VSCode Extension 2 | 3 | Fixed 10th February 2021 in https://github.com/microsoft/vscode-npm-scripts/commit/cdd5e507564e0cc0f60bcccf184822be3fd73e07 4 | 5 | https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26700 6 | 7 | ## Summary 8 | 9 | Remote code execution vulnerability in the [eg2.vscode-npm-script](https://marketplace.visualstudio.com/items?itemName=eg2.vscode-npm-script) 10 | (Tested on version 0.3.13) VSCode extension means that a malicious `.vscode/settings.json` in a project can cause 11 | remote code execution when a file named `package.json` is viewed. 12 | 13 | This vulnerability did not fall under any active Microsoft bug bounty program, but was reported to and handled by MSRC. 14 | 15 | ## Description 16 | 17 | Without a malicious `.vscode/settings.json` file in a repository, upon viewing a `package.json` file, with the 18 | `eg2.vscode-npm-script` extension installed, the command `npm ls --depth 0 --json` will be executed. 19 | 20 | By setting the `npm.bin` key in a projects `settings.json` eg. to `./payload.sh`, viewing the `package.json` will 21 | instead execute `./payload.sh ls --depth 0 --json` from the directory containing the `package.json`. 22 | 23 | This vulnerability breaks the assumption that source-code can be safely read. 24 | 25 | ## Example Attack 26 | 27 | An example of how this could be used by an attacker is: 28 | 29 | 1. Attacker publishes repository such as attached linux-poc 30 | 2. Target clones repository to read the source code in VSCode 31 | 3. Target views `package.json` 32 | 4. `payload.sh` is executed 33 | 34 | 35 | ## Remediation Options 36 | 37 | I've seen two ways of mitigating malicious VSCode Workspace `settings.json` 38 | 39 | ### Mitigation 1 - User Only Settings 40 | 41 | Forbid the settings to be set per workspace. This is already used by VSCode for `git.path`, `terminal.integrated.shell.linux` and a few other settings. 42 | 43 | This could break compatibility for some users, but has precedent. 44 | Reference: https://vscode.readthedocs.io/en/latest/getstarted/settings/#settings-and-security 45 | 46 | ### Mitigation 2 - Prompt for Confirmation 47 | 48 | If this setting is set in a workspace, prompt the user to confirm the setting before executing the binary. 49 | This will not break existing compatibility, and is the route taken by the ESLint Extension as of version 2.1.7. 50 | 51 | ## Proof of Concept 52 | 53 | ### Linux 54 | 55 | 1. Install vulnerable version (0.3.13 or earlier) of VSCode extension `eg2.vscode-npm-script` 56 | 2. Open `linux-poc` directory as a folder in VSCode 57 | 3. In VSCode click the `package.json` file to view it 58 | 4. The file `/tmp/output.txt` will be created to demonstrate execution 59 | 60 | 61 | ### Windows 62 | 63 | 1. Install vulnerable version (0.3.13 or earlier) of VSCode extension `eg2.vscode-npm-script` 64 | 2. Open `windows-poc` directory as a folder in VSCode 65 | 3. In VSCode click the `package.json` file to view it 66 | 4. `calc.exe` will be opened 67 | 68 | Note: I was unable to use a relative path for the binary in Windows, however this may be due to my lack of familiarity with Windows 69 | -------------------------------------------------------------------------------- /linux-poc/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "npm.bin": "./payload.sh" 3 | } 4 | -------------------------------------------------------------------------------- /linux-poc/package.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /linux-poc/payload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "RCE achieved" >> /tmp/output.txt 3 | echo "Ran: ./payload.sh $@" >> /tmp/output.txt 4 | -------------------------------------------------------------------------------- /windows-poc/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "npm.bin": "calc.exe" 3 | } 4 | -------------------------------------------------------------------------------- /windows-poc/package.json: -------------------------------------------------------------------------------- 1 | {} --------------------------------------------------------------------------------