Current Behavior:
I have an install script that needs to run the npm command to install a platform-specific package. I'm currently doing this by forwarding the install script's environment variables to the npm command. This automatically picks up most custom configuration from users including project-local .npmrc files. However, it doesn't work for config values that are exactly equal to false.
The problem appears to be that when the install script is run, the npm-lifecycle package sets all false config values in environment variables to an empty string instead, and then the npm/cli package ignores environment variables that are empty strings when reading environment variables back in.
Specifically, users that set strict-ssl=false in their .npmrc files will have that setting ignored because npm-lifecycle sets the npm_config_strict_ssl environment variable to an empty string, and then npm/cli ignores that and sets strict-ssl to true.
There is more info here: evanw/esbuild#565.
Expected Behavior:
There are three possible scenarios, and I'm not sure which one is the case here:
-
This could be considered a problem with npm-lifecycle. If so, I would expect that package to set environment variables for false config values to "false" instead of "".
-
This could be considered a problem with npm/cli. If so, I would expect that package to interpret environment variables that are present but empty strings as false values instead of ignoring them.
-
This behavior could be by design, or could be too risky to change. Then I would expect for my install script to have to handle this somehow.
Regardless of which case it is, I'd like to know if I should adapt my install script to translate npm_config_* environment variables that are empty strings to the string false. Even if this is fixed in npm itself, it would be great if my install script could be made to work with older npm versions.
I'm asking because I want to make sure there aren't going to be unintended consequences from doing this. It seems prudent to ask about this here since setting the strict-ssl option to false potentially has security consequences.
Steps To Reproduce:
Reproducing this is somewhat painful since it involves a custom registry. I am unfamiliar with custom registries (I'm just trying to solve a problem for a user of mine, and I don't have this problem myself) but I was able to reproduce this using https://verdaccio.org/.
- Install a custom registry locally (I used https://verdaccio.org/)
- Generate a self-signed SSL certificate for the local registry
- Create a directory with a
package.json file containing {}
- Create a
.npmrc with registry=(your local HTTPS registry URL) and strict-ssl=false
- Install the
esbuild package
When the issue happens, I see the errno DEPTH_ZERO_SELF_SIGNED_CERT error. This error only happens when the install script forwards environment variables to a nested npm command. It does not happen when manually I run the nested npm command myself.
The esbuild package may still install successfully because the install script is somewhat resilient and will fall back to a raw HTTP request to the npm registry, but that's not a solution for my user because their CI environment doesn't have direct internet access.
Environment:
- OS: macOS 10.15.7
- Node: 15.2.0
- npm: 6.14.9
Current Behavior:
I have an install script that needs to run the
npmcommand to install a platform-specific package. I'm currently doing this by forwarding the install script's environment variables to thenpmcommand. This automatically picks up most custom configuration from users including project-local.npmrcfiles. However, it doesn't work for config values that are exactly equal tofalse.The problem appears to be that when the install script is run, the
npm-lifecyclepackage sets allfalseconfig values in environment variables to an empty string instead, and then thenpm/clipackage ignores environment variables that are empty strings when reading environment variables back in.Specifically, users that set
strict-ssl=falsein their.npmrcfiles will have that setting ignored becausenpm-lifecyclesets thenpm_config_strict_sslenvironment variable to an empty string, and thennpm/cliignores that and setsstrict-ssltotrue.Here is where
falsebecomes"":https://github.com/npm/npm-lifecycle/blob/bfb6f73853a222a3f35a1a6651b0756816e2ed87/index.js#L464
Here is where
""is ignored, and becomestrue:cli/lib/config/core.js
Line 273 in 48753bb
There is more info here: evanw/esbuild#565.
Expected Behavior:
There are three possible scenarios, and I'm not sure which one is the case here:
This could be considered a problem with
npm-lifecycle. If so, I would expect that package to set environment variables forfalseconfig values to"false"instead of"".This could be considered a problem with
npm/cli. If so, I would expect that package to interpret environment variables that are present but empty strings asfalsevalues instead of ignoring them.This behavior could be by design, or could be too risky to change. Then I would expect for my install script to have to handle this somehow.
Regardless of which case it is, I'd like to know if I should adapt my install script to translate
npm_config_*environment variables that are empty strings to the stringfalse. Even if this is fixed in npm itself, it would be great if my install script could be made to work with older npm versions.I'm asking because I want to make sure there aren't going to be unintended consequences from doing this. It seems prudent to ask about this here since setting the
strict-ssloption tofalsepotentially has security consequences.Steps To Reproduce:
Reproducing this is somewhat painful since it involves a custom registry. I am unfamiliar with custom registries (I'm just trying to solve a problem for a user of mine, and I don't have this problem myself) but I was able to reproduce this using https://verdaccio.org/.
package.jsonfile containing{}.npmrcwithregistry=(your local HTTPS registry URL)andstrict-ssl=falseesbuildpackageWhen the issue happens, I see the
errno DEPTH_ZERO_SELF_SIGNED_CERTerror. This error only happens when the install script forwards environment variables to a nestednpmcommand. It does not happen when manually I run the nestednpmcommand myself.The
esbuildpackage may still install successfully because the install script is somewhat resilient and will fall back to a raw HTTP request to the npm registry, but that's not a solution for my user because their CI environment doesn't have direct internet access.Environment: