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


(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, 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! request to failed, reason: unable to get local issuer certificate

logfile shows this:

7093 verbose stack FetchError: request to 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
7101 error request to 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

(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)

strict-ssl = true


$ npm i github:lodash/lodash ms
npm WARN registry Unexpected warning for Miscellaneous Warning UNABLE_TO_GET_ISSUER_CERT_LOCALLY: request to failed, reason: unable to get local issuer certificate
npm WARN registry Using stale package data from 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:

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.