Skip to content

Bug: registerNoConfigDebug corrupts terminal PATH by missing semicolon separator on Windows #986

Description

@lihanspace

Bug: registerNoConfigDebug corrupts terminal PATH by missing semicolon separator on Windows

Environment

  • OS: Windows 11 Pro
  • VS Code: latest stable
  • ms-python.debugpy extension version: 2025.18.0
  • Other relevant extensions: ms-dotnettools.vscode-dotnet-runtime 3.0.0

Description

The registerNoConfigDebug function appends the noConfigScripts directory to the terminal PATH via EnvironmentVariableCollection.append(), but it decides whether to prepend a ; separator by checking process.env.PATH in the extension host process rather than the terminal's actual PATH. When process.env.PATH in the extension host ends with ; (e.g. because another extension like ms-dotnettools.vscode-dotnet-runtime modifies it directly via process.env.PATH += delimiter + path), the separator is omitted, corrupting the terminal PATH.

Steps to Reproduce

  1. Install ms-python.debugpy alongside an extension that directly mutates process.env.PATH in the extension host (e.g. ms-dotnettools.vscode-dotnet-runtime).
  2. Ensure the user PATH contains entries like C:\Users\<user>\.local\bin near the end.
  3. Open a new integrated terminal in VS Code.
  4. Run: $env:Path -split ';' | Select-String '\.local\\bin'

Expected Behavior

C:\Users\<user>\.local\bin

Each PATH entry is properly separated by ;.

Actual Behavior

C:\Users\<user>\.local\binc:\Users\<user>\.vscode\extensions\ms-python.debugpy-2025.18.0-win32-x64\bundled\scripts\noConfigScripts

The two paths are concatenated without a ; separator, making both entries unresolvable. Any executable in .local\bin (e.g. claude) becomes unavailable in the VS Code terminal while working fine in a standalone terminal.

Root Cause

In src/extension/noConfigDebugger/noConfigDebugAdapter.ts (minified in dist/extension.js):

const noConfigPath = path.join(extensionPath, "bundled", "scripts", "noConfigScripts");
const delimiter = process.platform === "win32" ? ";" : ":";
const currentPath = process.env.PATH || "";
const value = currentPath.length > 0 && !currentPath.endsWith(delimiter)
    ? `${delimiter}${noConfigPath}`
    : noConfigPath;
collection.append("PATH", value);

The issue is that process.env.PATH reflects the extension host process environment, which can be modified by other extensions at runtime (e.g. process.env.PATH += ";" + somePath). However, EnvironmentVariableCollection.append() operates on the terminal environment, which is constructed independently by VS Code from the system/user PATH plus all extensions' EnvironmentVariableCollection mutations.

When the extension host's process.env.PATH happens to end with ; (due to another extension's direct mutation), the condition !currentPath.endsWith(delimiter) evaluates to false, so the delimiter is omitted. But the terminal's actual PATH does not end with ;, resulting in a corrupted concatenation.

Suggested Fix

Always prepend the delimiter when appending, since EnvironmentVariableCollection.append() performs raw string concatenation:

const value = `${delimiter}${noConfigPath}`;
collection.append("PATH", value);

This is safe even if the terminal PATH already ends with ; — it would just produce an empty entry (;;), which is harmless and is the standard defensive practice for PATH manipulation.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage-neededNeeds assignment to the proper sub-team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions