Skip to content

MSBuild should sanitize environment block on startup #5726

@asklar

Description

@asklar

Issue Description

We have a command-line set of tools written in JavaScript (nodeJS) which launch msbuild. Our command line tool is launched via yarn.

Some tools like Yarn will spawn nodeJS via CreateProcess and pass an environment block that contains duplicated environment variables, e.g:
image
See how the same environment variable is set twice, with different casing.

Windows doesn't do any checking of environment variables being duplicated in CreateProcess so the node.exe process gets created with the two names. Then in our case, MSBuild gets launched from within node.exe, which later launches CL.exe and other build tools.

The Azure DevOps CI pipeline sets NPM_CONFIG_CACHE (all caps), while yarn will add the lowercase npm_config_cache to the environment block when a process is launched via child_process.exec(). See https://github.com/actions/virtual-environments/blob/b47ba413c9bd9411407b8a5cf18e2c14ea8bda78/images/win/scripts/Installers/Install-NodeLts.ps1.

As a result of this, we are hitting an error in our CI because MultiTaskTool is probably putting variables in a case-insensitive dictionary and doesn't expect to find the same variable twice:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(375,5): error MSB6001: Invalid command line switch for "CL.exe". System.ArgumentException: Item has already been added. Key in dictionary: 'NPM_CONFIG_CACHE' Key being added: 'npm_config_cache' [D:\a\1\s\vnext\Common\Common.vcxproj]

Steps to Reproduce

nodeJS file: test.js

console.log(process.env);
child_process.execSync("path_to_msbuild/msbuild.exe myproj.vcxproj");

myproj.vcxproj, just a regular C++ project

in packages.json add an entry e.g.

"run": "test.js"

in cmd, set NPM_CONFIG_CACHE

then run yarn run. See that the console.log in test.js shows the variable duplicated, and see that the task to launch CL breaks with an error similar to the above.

Expected Behavior

Build doesn't break

Actual Behavior

Build breaks :)

Analysis

Arguably System.Diagnostics.Process should sanitize its environment variables, but I'm not sure if that is fixable without introducing breaking changes so that's why I'd like msbuild to guard against this.

Versions & Configurations

all versions

Attach a binlog

msbuild_2720.zip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions