microsoft / microsoft/vscode

Extensions can pollute process.env inherited by unrelated extensions and child processes

Open
#325,459 0 comments 1 reaction 1 assignee Claimed by @alexdima View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

Does this issue occur when all extensions are disabled?: No. The defect is in isolation between extensions running in the same extension host and therefore requires at least one extension.

- VS Code Version: 1.128.0 (fc3def6774c76082adf699d366f31a557ce5573f), x64
- OS Version: Windows 11 10.0.26200 (build 26200)

## Problem

An extension can mutate the extension host's global `process.env`. The mutation is then visible to unrelated extensions and is inherited by child processes that those extensions launch.

A faulty extension currently sets `DEBUG=release`. A separate Java/Gradle extension launches its language server from the same affected environment. The value then propagates through Gradle to a Spring Boot application, where Spring Boot interprets `DEBUG` as its global debug switch and emits framework DEBUG logs plus the full conditions evaluation report.

The originating extension defect is tracked separately at openai/codex#13694. This report is about the VS Code platform boundary that permits one extension's accidental global environment mutation to affect unrelated extensions and their tools.

## Generic reproduction

Use two minimal desktop extensions assigned to the same local extension host.

Extension A activation:

```js
exports.activate = function () {
process.env.VSCODE_EXTENSION_ISOLATION_REPRO = 'from-extension-a';
};
```

Extension B activation:

```js
const cp = require('child_process');

exports.activate = function () {
console.log(process.env.VSCODE_EXTENSION_ISOLATION_REPRO);
cp.execFile(
process.env.ComSpec,
['/d', '/s', '/c', 'echo %VSCODE_EXTENSION_ISOLATION_REPRO%'],
(_, stdout) => console.log(stdout.trim())
);
};
```

Steps:

1. Start an Extension Development Host with both extensions.
2. Activate extension A.
3. Activate extension B.
4. Observe extension B reading `from-extension-a`.
5. Observe the unrelated child process also inheriting `from-extension-a`.

## Actual result

A global environment mutation made by extension A is observable by extension B and inherited by extension B's child process. In the real-world case the confirmed chain is:

```text
extension A -> shared extension host process.env
-> extension B child process
-> Gradle daemon
-> Spring Boot application
```

Closing terminals, restarting VS Code, and rebooting Windows do not solve the problem because the extension repeats the mutation when the new extension host starts.

## Expected result

An extension should not be able to unintentionally alter the environment observed by unrelated extensions and their child processes. Possible platform-level approaches include isolating extension environments, restoring the host environment after extension callbacks, or providing a child-process environment boundary that does not inherit arbitrary mutations from unrelated extensions.

At minimum, the shared global behavior and the requirement for extension authors to avoid mutating `process.env` should be explicitly documented.

## Confirmed A/B evidence

With the same downstream application and configuration:

- inherited `DEBUG=release`: framework DEBUG lines and the Spring Boot conditions evaluation report appear
- removing `DEBUG` immediately before the final child process: the application starts with zero DEBUG lines and no conditions evaluation report

This demonstrates cross-extension environment propagation rather than an application logging configuration change.

Related originating-extension defect: https://github.com/openai/codex/issues/13694

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.