{"record":{"id":"f83466954f8eb84f","repo":"decolua/9router","slug":"user-canceled-authorization-certificate-install","errorCode":null,"errorMessage":"User canceled authorization | Certificate install failed","messagePattern":"User canceled authorization \\| Certificate install failed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mitm/cert/install.js","lineNumber":115,"sourceCode":"  if (IS_WIN) {\n    await installCertWindows(certPath);\n  } else if (IS_MAC) {\n    await installCertMac(sudoPassword, certPath);\n  } else {\n    await installCertLinux(sudoPassword, certPath);\n  }\n}\n\nasync function installCertMac(sudoPassword, certPath) {\n  // Remove all old certs with same name first to avoid duplicate/stale cert conflict\n  const deleteOld = `security delete-certificate -c \"9Router MITM Root CA\" /Library/Keychains/System.keychain 2>/dev/null || true`;\n  const install = `security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain \"${certPath}\"`;\n  try {\n    await execWithPassword(`${deleteOld} && ${install}`, sudoPassword);\n    log(\"🔐 Cert: ✅ installed to system keychain\");\n  } catch (error) {\n    const msg = error.message?.includes(\"canceled\") ? \"User canceled authorization\" : \"Certificate install failed\";\n    throw new Error(msg);\n  }\n}\n\nasync function installCertWindows(certPath) {\n  // Auto-elevate via UAC popup if not admin (zero popup if already admin).\n  // Delete any stale cert with same CN before adding to avoid duplicates.\n  const script = `\n    certutil -delstore Root ${quotePs(ROOT_CA_CN)} 2>$null | Out-Null\n    $exit = & certutil -addstore Root ${quotePs(certPath)} 2>&1\n    if ($LASTEXITCODE -ne 0) { throw \"certutil exit $LASTEXITCODE\" }\n  `;\n  try {\n    await runElevatedPowerShell(script);\n    log(\"🔐 Cert: ✅ installed to Windows Root store\");\n  } catch (e) {\n    throw new Error(`Failed to install certificate: ${e.message}`);\n  }\n}","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/mitm/cert/install.js#L97-L133","documentation":"installCertMac() runs `security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain` via execWithPassword (sudo). If the command exits non-zero, the error is normalized: 'User canceled authorization' when the underlying error mentions 'canceled' (user dismissed the sudo/auth prompt), otherwise the generic 'Certificate install failed'.","triggerScenarios":"installCert() on macOS when: the user dismisses/cancels the sudo password dialog, the sudo password is wrong, `security add-trusted-cert` rejects the cert, or the System.keychain is locked/unwritable.","commonSituations":"User walks away from the auth dialog and it times out or is dismissed; wrong sudo password typed into the prompt; corporate-managed Macs with MDM restrictions blocking trustRoot insertion; macOS security-policy changes requiring interactive approval of root certs.","solutions":["Re-run the install and accept the authorization dialog when it appears","Verify the sudo password is correct by testing `sudo -v` in a terminal","Check MDM/security policy allows adding trustRoot certs to the System keychain","Manually run `security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <cert>` to see the raw error"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check cert exists and macOS is not under a policy that blocks keychain writes is not directly queryable;\n// at minimum verify the binary and cert:\nawait exec('which security');\nif (!fs.existsSync(certPath)) throw new Error('cert missing before macOS install');","typeGuard":null,"tryCatchPattern":"try {\n  await installCert(sudoPassword, certPath);\n} catch (e) {\n  if (e.message === 'User canceled authorization') {\n    // prompt user to retry and accept the dialog\n  } else if (e.message === 'Certificate install failed') {\n    // fall back to manual instructions\n  } else throw e;\n}","preventionTips":["Surface a clear UI prompt before triggering the sudo dialog so the user expects it","Retry once automatically on 'User canceled authorization'","Document the manual `security add-trusted-cert` command as a fallback"],"tags":["macos","certificate","sudo","keychain"],"backgroundTag":"sudo-authentication-failed","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}