Install from private repo using cafile and strict-ssl FAILS when encountering repository dependency

cli
help-wanted
good-first-patch
priority:medium
triaged

(Christoph Werner) #1

What I Wanted to Do

I wanted to configure a project via .npmrc so it installs dependencies from a private repository instead of the public npm registry.

In order to do so, i added a few lines of configuration to my .npmrc:

_auth = *********
registry = https://internal/artifactory/api/npm/npm/
cafile = /path/to/cert-path.pem
always-auth = true
strict-ssl = true

The private artifactory instance has an npm feed/repository, which is available at https://internal/artifactory/api/npm/npm/. It also has an SSL certificate provided by GlobalSign. In order to get strict-ssl = true working, i had to export all certificates on the certification path up to the GlobalSign CA root certificate as .pem files, concatenate them to a single file the order from leaf to root and use that as the cafile.

Now, when running npm install without any repository dependencies in my dependency tree, everything is splendid. However, once npm install encounters a repository dependency, things break.

What Happened Instead

When encountering a repository dependency in the dependency tree, npm install fails.

In our case, https://github.com/okonet/listr-update-renderer/tarball/upgrade-log-update from the lint-staged@8.0.4 dependencies is the culprit. When running npm i with this in the dependency tree, install fails:

npm ERR! code UNABLE_TO_GET_ISSUER_CERT_LOCALLY
npm ERR! errno UNABLE_TO_GET_ISSUER_CERT_LOCALLY
npm ERR! request to https://github.com/okonet/listr-update-renderer/tarball/upgrade-log-update failed, reason: unable to get local issuer certificate

logfile shows this:

7093 verbose stack FetchError: request to https://github.com/okonet/listr-update-renderer/tarball/upgrade-log-update failed, reason: unable to get local issuer certificate
7093 verbose stack     at ClientRequest.req.on.err (/usr/lib/node_modules/npm/node_modules/node-fetch-npm/src/index.js:68:14)
7093 verbose stack     at ClientRequest.emit (events.js:182:13)
7093 verbose stack     at TLSSocket.socketErrorListener (_http_client.js:382:9)
7093 verbose stack     at TLSSocket.emit (events.js:182:13)
7093 verbose stack     at emitErrorNT (internal/streams/destroy.js:82:8)
7093 verbose stack     at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
7093 verbose stack     at process._tickCallback (internal/process/next_tick.js:63:19)
7094 verbose cwd /path/to/website
7095 verbose Linux 4.4.0-43-Microsoft
7096 verbose argv "/usr/bin/node" "/usr/bin/npm" "i"
7097 verbose node v10.2.1
7098 verbose npm  v6.2.0
7099 error code UNABLE_TO_GET_ISSUER_CERT_LOCALLY
7100 error errno UNABLE_TO_GET_ISSUER_CERT_LOCALLY
7101 error request to https://github.com/okonet/listr-update-renderer/tarball/upgrade-log-update failed, reason: unable to get local issuer certificate
7102 verbose exit [ 1, true ]

Reproduction Steps

Have a private feed, point npm to it via .npmrc, set strict-ssl to true, provide the certificate chain as cafile, run npm i with repository dependencies (in our case: from GitHub) in the dependency tree.

Platform Info

$ npm --versions
{ 'paderbornjs-website': '1.0.0',
  npm: '6.2.0',
  ares: '1.14.0',
  cldr: '33.0',
  http_parser: '2.8.0',
  icu: '61.1',
  modules: '64',
  napi: '3',
  nghttp2: '1.29.0',
  node: '10.2.1',
  openssl: '1.1.0h',
  tz: '2018c',
  unicode: '10.0',
  uv: '1.20.3',
  v8: '6.6.346.32-node.8',
  zlib: '1.2.11' }
$ node -p process.platform
linux

(Lars Willighagen) #2

I can’t reproduce this on npm v6.4.1 with the closest settings I could easily produce:

.npmrc: (literally, just an invalid certificate)

ca="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----"
strict-ssl = true

Log

$ npm i github:lodash/lodash ms
npm WARN registry Unexpected warning for https://registry.npmjs.org/: Miscellaneous Warning UNABLE_TO_GET_ISSUER_CERT_LOCALLY: request to https://registry.npmjs.org/ms failed, reason: unable to get local issuer certificate
npm WARN registry Using stale package data from https://registry.npmjs.org/ due to a request error during revalidation.
npm WARN 068@1.0.0 No repository field.

+ ms@2.1.1
+ lodash@4.17.4
added 2 packages in 37.675s

I’ll look further though.

Edit: nevermind, can reproduce now, it was specifically the use of a GitHub tarball URL instead of the more normal github:okonet/listr-update-renderer#upgrade-log-update.


(Lars Willighagen) #3

Also relevant: https://github.com/okonet/lint-staged/issues/533

So fetching a remote tarball URL in pacote is delegated to the regular registry fetcher:

This evidently causes problems when inheriting config, possibly not limited to ca and cafile. I don’t really know a way forward here, as the remote spec types seems to be used both for external public registries and remote tarballs, although either way, the cas for the configured registry shouldn’t be used.