fix(mitm): add Linux cert install and skip sudo password when root#1999
Conversation
Add Linux certificate management via update-ca-certificates for Docker support. Skip sudo password validation when running as root, matching the existing cli-tools route behavior.
There was a problem hiding this comment.
Code Review
This pull request introduces Linux support for MITM certificate management and allows root users on non-Windows platforms to bypass the sudo password requirement. The review feedback suggests optimizing the Linux certificate installation process by combining multiple sudo commands into a single shell execution to reduce password prompts. Additionally, it recommends refining error handling to be platform-appropriate, avoiding the aggressive --fresh flag during certificate updates to prevent side effects, and ensuring original error messages are preserved for better debugging.
| await execFileWithPassword("sudo", ["-S", "mkdir", "-p", LINUX_CA_DIR], sudoPassword); | ||
| await execFileWithPassword("sudo", ["-S", "cp", certPath, LINUX_CERT_DEST], sudoPassword); | ||
| await execFileWithPassword("sudo", ["-S", "update-ca-certificates"], sudoPassword); |
There was a problem hiding this comment.
Executing multiple sequential sudo commands is inefficient and will result in multiple password prompts if the user is not running as root and sudo is configured to require a password for each invocation. It is better to combine these into a single command string executed via sh -c to ensure only one authorization is needed.
| await execFileWithPassword("sudo", ["-S", "mkdir", "-p", LINUX_CA_DIR], sudoPassword); | |
| await execFileWithPassword("sudo", ["-S", "cp", certPath, LINUX_CERT_DEST], sudoPassword); | |
| await execFileWithPassword("sudo", ["-S", "update-ca-certificates"], sudoPassword); | |
| const command = `mkdir -p "${LINUX_CA_DIR}" && cp "${certPath}" "${LINUX_CERT_DEST}" && update-ca-certificates`; | |
| await execFileWithPassword("sudo", ["-S", "sh", "-c", command], sudoPassword); |
| const msg = message.includes("canceled") | ||
| ? "User canceled authorization" | ||
| : "Certificate install failed"; |
There was a problem hiding this comment.
The check for the string "canceled" in the error message is specific to macOS security tools and is unlikely to be triggered by standard Linux sudo or system commands. On Linux, failures are more likely to be due to incorrect passwords or permission issues. Consider refining the error handling to be platform-appropriate or more generic.
| if (fs.existsSync(LINUX_CERT_DEST)) { | ||
| await execFileWithPassword("sudo", ["-S", "rm", "-f", LINUX_CERT_DEST], sudoPassword); | ||
| } | ||
| await execFileWithPassword("sudo", ["-S", "update-ca-certificates", "--fresh"], sudoPassword); |
There was a problem hiding this comment.
The --fresh flag for update-ca-certificates is quite aggressive as it re-generates all symlinks in /etc/ssl/certs and removes any that are broken. While it ensures the removed certificate is fully purged, it may have unintended side effects on other manually managed certificates in the system store. A standard update-ca-certificates call is usually sufficient after deleting the source file.
| await execFileWithPassword("sudo", ["-S", "update-ca-certificates", "--fresh"], sudoPassword); | |
| await execFileWithPassword("sudo", ["-S", "update-ca-certificates"], sudoPassword); |
| } | ||
| await execFileWithPassword("sudo", ["-S", "update-ca-certificates", "--fresh"], sudoPassword); | ||
| } catch (err) { | ||
| throw new Error("Failed to uninstall certificate"); |
There was a problem hiding this comment.
The actual error message is being swallowed here, which makes debugging difficult if the uninstallation fails. It is better to include the original error message in the thrown Error.
| throw new Error("Failed to uninstall certificate"); | |
| throw new Error(`Failed to uninstall certificate: ${getErrorMessage(err)}`); |
Turbopack resolveAlias (@/mitm/manager → manager.stub.ts) was designed
for build-time safety but Next.js applies aliases to ALL imports —
including dynamic ones. This caused await import("@/mitm/manager") at
runtime to load the stub, which silently returned fake {running: true}
without spawning the MITM proxy. The UI showed "MITM proxy started"
but nothing was actually running.
Fix introduces a two-path design:
- @/mitm/manager → stub (build-time, safe for Turbopack)
- @/mitm/manager.runtime → real manager (runtime, bypasses alias)
Route handlers now dynamic-import from manager.runtime, which
re-exports from ./manager and does NOT match the alias pattern.
Additional fixes:
- Make stub throw explicit errors at runtime so misconfiguration is
immediately visible instead of silently faking success
- Add server.cjs to outputFileTracingIncludes (NFT trace) and Dockerfile
COPY so the MITM server binary exists in standalone/Docker output
|
Thank you @NekoMonci12 for your contribution! This has been reviewed and is now merged into |
72d0e1f
into
diegosouzapw:release/v3.8.0
Summary
Add Linux certificate management via update-ca-certificates for Docker support. Skip sudo password validation when running as root, matching the existing cli-tools route behavior.
Turbopack resolveAlias (@/mitm/manager → manager.stub.ts) was designed
for build-time safety but Next.js applies aliases to ALL imports
including dynamic ones. This caused await import("@/mitm/manager") at
runtime to load the stub, which silently returned fake {running: true}
without spawning the MITM proxy. The UI showed "MITM proxy started"
but nothing was actually running.
Fix introduces a two-path design:
Route handlers now dynamic-import from manager.runtime, which
re-exports from ./manager and does NOT match the alias pattern.
Additional fixes:
immediately visible instead of silently faking success
COPY so the MITM server binary exists in standalone/Docker output
Related Issues
Validation
npm run lintnpm run test:unitnpm run test:coverage>= 60%for statements, lines, functions, and branchesTests Added Or Updated
Coverage Notes
src/,open-sse/,electron/, orbin/, explain which tests cover the change.Reviewer Notes