diff --git a/DevProxy/Commands/CertCommand.cs b/DevProxy/Commands/CertCommand.cs index e5d6bf412..bff35ed69 100644 --- a/DevProxy/Commands/CertCommand.cs +++ b/DevProxy/Commands/CertCommand.cs @@ -15,7 +15,7 @@ sealed class CertCommand : Command private readonly ILoggerFactory _loggerFactory; private readonly Option _forceOption = new("--force", "-f") { - Description = "Don't prompt for confirmation when removing the certificate" + Description = "Don't prompt for confirmation when removing the certificate. Required for non-interactive use (CI, piped stdin, automation)." }; public CertCommand(ILogger logger, ILoggerFactory loggerFactory) : @@ -74,7 +74,7 @@ private async Task EnsureCertAsync() _logger.LogTrace("EnsureCertAsync() finished"); } - public void RemoveCert(ParseResult parseResult) + public int RemoveCert(ParseResult parseResult) { _logger.LogTrace("RemoveCert() called"); @@ -83,10 +83,17 @@ public void RemoveCert(ParseResult parseResult) var isForced = parseResult.GetValue(_forceOption); if (!isForced) { + if (Console.IsInputRedirected || + Environment.GetEnvironmentVariable("CI") is not null) + { + _logger.LogError("Confirmation required but running in non-interactive mode. Use --force to skip confirmation."); + return 1; + } + var isConfirmed = PromptConfirmation("Do you want to remove the root certificate", acceptByDefault: false); if (!isConfirmed) { - return; + return 0; } } @@ -111,10 +118,12 @@ public void RemoveCert(ParseResult parseResult) } _logger.LogInformation("DONE"); + return 0; } catch (Exception ex) { _logger.LogError(ex, "Error removing certificate"); + return 1; } finally { diff --git a/DevProxy/Proxy/ProxyEngine.cs b/DevProxy/Proxy/ProxyEngine.cs index 851e74cb7..0fa084480 100755 --- a/DevProxy/Proxy/ProxyEngine.cs +++ b/DevProxy/Proxy/ProxyEngine.cs @@ -231,8 +231,20 @@ private void FirstRunSetup() Console.WriteLine(); Console.WriteLine("Dev Proxy uses a self-signed certificate to intercept and inspect HTTPS traffic."); - Console.Write("Update the certificate in your Keychain so that it's trusted by your browser? (Y/n): "); - var answer = Console.ReadLine()?.Trim(); + + string? answer; + if (Console.IsInputRedirected || + Environment.GetEnvironmentVariable("CI") is not null) + { + // Non-interactive mode, default to trusting the certificate + _logger.LogInformation("Non-interactive mode detected. Defaulting to trusting the certificate."); + answer = "y"; + } + else + { + Console.Write("Update the certificate in your Keychain so that it's trusted by your browser? (Y/n): "); + answer = Console.ReadLine()?.Trim(); + } if (string.Equals(answer, "n", StringComparison.OrdinalIgnoreCase)) {