Skip to content

Commit 4b28edd

Browse files
committed
fix(dev): recommend a CA root instead of disabling TLS verification
1 parent e32ea88 commit 4b28edd

2 files changed

Lines changed: 24 additions & 11 deletions

File tree

‎packages/nuxt-cli/src/dev/cert.ts‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Buffer } from 'node:buffer'
33
import{execFileSync}from'node:child_process'
44
import{createHash,createPrivateKey,X509Certificate}from'node:crypto'
55
import{existsSync,readFileSync}from'node:fs'
6-
import{readFile}from'node:fs/promises'
6+
import{readFile,writeFile}from'node:fs/promises'
77
import{isIP}from'node:net'
88
importprocessfrom'node:process'
99

@@ -31,6 +31,12 @@ export interface ResolvedCertificate {
3131
/** Path the `pfx` buffer was read from, for reporting back to `devServer.https`. */
3232
pfxPath?: string
3333
passphrase?: string
34+
/**
35+
* Directory holding the local certificate authority `mkcert` issued the
36+
* certificate from. Node does not read the system trust store, so a client
37+
* running under Node needs this root passed explicitly.
38+
*/
39+
caRoot?: string
3440
}
3541

3642
exportasyncfunctionresolveCertificate(options: HTTPSOptions): Promise<ResolvedCertificate>{
@@ -57,17 +63,20 @@ async function generateCertificate(options: HTTPSOptions): Promise<ResolvedCerti
5763
constcertPath=join(dir,'cert.pem')
5864
constkeyPath=join(dir,'key.pem')
5965

66+
constcaRootPath=join(dir,'caroot')
67+
6068
if(!isCertificateUsable(certPath,keyPath,domains)){
61-
constgenerated=awaitgenerateWithMkcert(certPath,keyPath,domains)
62-
||generateWithOpenssl(certPath,keyPath,domains,options.validityDays)
63-
if(!generated){
69+
constcaRoot=awaitgenerateWithMkcert(certPath,keyPath,domains)
70+
if(caRoot===undefined&&!generateWithOpenssl(certPath,keyPath,domains,options.validityDays)){
6471
thrownewActionableError('Could not generate a development certificate. Install `mkcert` (https://github.com/FiloSottile/mkcert) or provide `--https.cert` and `--https.key`.')
6572
}
73+
awaitwriteFile(caRootPath,caRoot??'','utf8').catch(error=>debug('Could not record the certificate authority root:',error))
6674
}
6775

6876
return{
6977
cert: awaitreadFile(certPath,'utf8'),
7078
key: awaitreadFile(keyPath,'utf8'),
79+
caRoot: awaitreadFile(caRootPath,'utf8').then(value=>value.trim()||undefined).catch(()=>undefined),
7180
}
7281
}
7382

@@ -96,19 +105,20 @@ function isCertificateUsable(certPath: string, keyPath: string, domains: string[
96105
}
97106
}
98107

99-
asyncfunctiongenerateWithMkcert(certPath: string,keyPath: string,domains: string[]): Promise<boolean>{
108+
/** The certificate authority root `mkcert` issued from, or `undefined` if it could not be used. */
109+
asyncfunctiongenerateWithMkcert(certPath: string,keyPath: string,domains: string[]): Promise<string|undefined>{
100110
constbinary=awaitresolveMkcert()
101111
if(!binary){
102-
returnfalse
112+
returnundefined
103113
}
104114
try{
105115
execFileSync(binary,['-install'],{stdio: ['inherit','ignore','inherit']})
106116
execFileSync(binary,['-cert-file',certPath,'-key-file',keyPath, ...domains],{stdio: 'ignore'})
107-
returntrue
117+
returnexecFileSync(binary,['-CAROOT'],{encoding: 'utf8'}).trim()||''
108118
}
109119
catch(error){
110120
debug('Failed to generate certificate with mkcert:',error)
111-
returnfalse
121+
returnundefined
112122
}
113123
}
114124

‎packages/nuxt-cli/src/dev/utils.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { ActionableError } from '../utils/errors'
2828
import{clearBuildDir}from'../utils/fs'
2929
import{loadKit}from'../utils/kit'
3030
import{acquireLock,formatLockError,getTakeoverPid,updateLock}from'../utils/lockfile'
31-
import{debug,writeNotice}from'../utils/logger'
31+
import{debug,logger,writeNotice}from'../utils/logger'
3232
import{loadNuxtManifest,resolveNuxtManifest,writeNuxtManifest}from'../utils/nuxt'
3333
import{renderError,renderErrorAnsi}from'./error-lazy'
3434
import{listen}from'./listen'
@@ -682,8 +682,11 @@ export class NuxtDevServer extends EventEmitter<DevServerEventMap> {
682682
this.#currentNuxt.options.devServer.url=getAddressURL(addr,!!this.listener.https)
683683
this.#currentNuxt.options.devServer.https=resolveDevServerHTTPS(this.listener.https)
684684

685-
if(this.listener.https&&!process.env.NODE_TLS_REJECT_UNAUTHORIZED){
686-
console.warn('You might need `NODE_TLS_REJECT_UNAUTHORIZED=0` environment variable to make https work.')
685+
if(this.listener.https&&process.env.NODE_TLS_REJECT_UNAUTHORIZED!=='0'&&!process.env.NODE_EXTRA_CA_CERTS){
686+
constcaRoot=this.listener.https.caRoot
687+
logger.warn(caRoot
688+
? `Node does not read your system trust store, so requests to this server from Node will not trust its certificate.\n Set \`NODE_EXTRA_CA_CERTS=${join(caRoot,'rootCA.pem')}\` to fix that.`
689+
: 'Node does not read your system trust store, so requests to this server from Node will not trust its certificate.\n Set `NODE_EXTRA_CA_CERTS` to the certificate authority that issued it, or install `mkcert` for a locally-trusted certificate.')
687690
}
688691

689692
constkit=awaitloadKit(this.options.cwd)

0 commit comments

Comments
 (0)