{"record":{"id":"295d17c5bcca9a28","repo":"decolua/9router","slug":"failed-to-trust-certificate-e-message","errorCode":null,"errorMessage":"Failed to trust certificate: ${e.message}","messagePattern":"Failed to trust certificate: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mitm/manager.js","lineNumber":567,"sourceCode":"\n  // Step 1.5: Auto-install Root CA if not trusted yet\n  const { checkCertInstalled } = require(\"./cert/install\");\n  const rootCATrusted = await checkCertInstalled(rootCACertPath);\n  const linuxNoSystemTrust = !IS_WIN && !IS_MAC && !isSudoAvailable();\n  if (!rootCATrusted) {\n    log(\"🔐 Cert: not trusted → installing...\");\n    const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();\n    if (linuxNoSystemTrust) {\n      log(`🔐 Cert: skipping system trust (no sudo). Install ${rootCACertPath} as a trusted CA on machines that use this proxy.`);\n    } else {\n      if (!password && isSudoPasswordRequired()) {\n        throw new Error(\"Sudo password required to install Root CA certificate\");\n      }\n      try {\n        await installCert(password, rootCACertPath);\n        log(\"🔐 Cert: ✅ trusted\");\n      } catch (e) {\n        throw new Error(`Failed to trust certificate: ${e.message}`);\n      }\n    }\n  } else {\n    log(\"🔐 Cert: already trusted ✅\");\n  }\n\n  // Step 2: Spawn server (Root CA already installed in Step 1.5)\n  // Verify server.js exists — recopy if runtime file was deleted (antivirus/cleanup)\n  let effectiveServerPath = SERVER_PATH;\n  if (!effectiveServerPath || !fs.existsSync(effectiveServerPath)) {\n    log(`[MITM] server.js missing at ${effectiveServerPath} → recopying`);\n    effectiveServerPath = ensureRuntimeServer(resolveBundledServerPath());\n    if (!effectiveServerPath || !fs.existsSync(effectiveServerPath)) {\n      throw new Error(`MITM server.js not found at ${effectiveServerPath}. Reinstall 9router.`);\n    }\n  }\n  const mitmRouterBase = await resolveMitmRouterBaseUrl();\n  log(`🚀 Starting server... (router: ${mitmRouterBase})`);","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/mitm/manager.js#L549-L585","documentation":"This wraps any failure from installCert(password, rootCACertPath) — the platform-specific routine that adds the 9Router Root CA to the OS trust store (security/updates settings on macOS, certutil/registry on Windows, update-ca-certificates equivalents on Linux). The original error message is preserved in the template so the root cause (command missing, permission denied, timeout, keychain rejection) surfaces as 'Failed to trust certificate: <cause>'.","triggerScenarios":"installCert's underlying command fails: sudo password wrong/expired, certutil/security/update-ca-trust binary missing or non-PATH, keychain denies the add, Linux without the expected CA directory, or the CA file is corrupt/just regenerated mid-flight.","commonSituations":"Wrong sudo password saved in the encrypted store (message like 'incorrect password attempts'); minimal Docker/CI image lacking certutil or update-ca-certificates; corporate-managed macOS where the keychain blocks adding root CAs programmatically; rootCA.crt truncated or expired after an interrupted generateCert; SELinux/AppArmor blocking writes to the system CA dir.","solutions":["Read the underlying cause in the message and fix accordingly (wrong password → re-save it; missing binary → install the ca-certificates package)","Manually trust the CA: `sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/.9router/mitm/rootCA.crt` (macOS) or `sudo cp rootCA.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates` (Debian/Ubuntu), then restart — checkCertInstalled will skip install","Regenerate the CA if the file is corrupt/expired: delete rootCA.crt/rootCA.key under the MITM_DIR so startServer regenerates them","Use the linuxNoSystemTrust mode (run without sudo availability on Linux) and distribute the CA to client machines yourself"],"exampleFix":"// before: opaque failure at runtime\nawait startServer(apiKey, password);\n// after: pre-trust manually so installCert is skipped\nexecSync(`sudo cp ${mitmDir}/rootCA.crt /usr/local/share/ca-certificates/9router.crt && sudo update-ca-certificates`);\nawait startServer(apiKey);","handlingStrategy":"fallback","validationCode":"const fs = require('fs');\nconst certPath = require('os').homedir() + '/.9router/mitm/rootCA.crt';\nfunction caFilesLookValid() {\n  try {\n    const pem = fs.readFileSync(certPath, 'utf-8');\n    return pem.includes('BEGIN CERTIFICATE') && pem.includes('END CERTIFICATE');\n  } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await startServer(apiKey, password);\n} catch (e) {\n  const m = /Failed to trust certificate: (.+)/.exec(e.message);\n  if (m) {\n    console.error('CA install failed:', m[1]);\n    // fallback: install the CA manually with the platform tool, then retry\n    execSync(`sudo cp ${certPath} /usr/local/share/ca-certificates/9router.crt && sudo update-ca-certificates`);\n    await startServer(apiKey, password);\n  } else throw e;\n}","preventionTips":["Keep certutil/security/update-ca-certificates installed on minimal images","Regenerate the CA if rootCA.crt/key are truncated or expired rather than retrying installs over a bad file","Re-save the encrypted sudo password after any OS password change","On managed macOS, pre-approve the CA via MDM so keychain programmatic adds succeed"],"tags":["certificate","tls","trust-store","sudo","mitm"],"backgroundTag":"certificate-trust-failed","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}