diff --git a/docs/source/user_guide/troubleshooting.rst b/docs/source/user_guide/troubleshooting.rst index 9f8290bb75..f38f39177b 100644 --- a/docs/source/user_guide/troubleshooting.rst +++ b/docs/source/user_guide/troubleshooting.rst @@ -174,3 +174,48 @@ See `#2592 `_, `#1446 `_ for more details. + + +SSL Certificate Verification Issues +------------------------------------ + +SSL/TLS certificate verification errors +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you encounter SSL certificate verification errors, especially in corporate environments with MITM HTTPS proxies, you have several options: + +**Use the OS trust store (Recommended for corporate environments)** + +Set ``ssl_verify`` to ``truststore`` to use your operating system's certificate trust store. This is particularly useful when your organization has installed custom CA certificates in the system trust store:: + + micromamba config set ssl_verify truststore + +Or in your :file:`~/.condarc` or :file:`~/.mambarc` file: + +.. code-block:: yaml + + ssl_verify: truststore + +On Windows, this uses the Windows certificate store via Schannel. On macOS and Linux, this uses the system certificate paths. + +**Use a custom certificate file** + +If you have a specific CA certificate bundle, you can point to it directly:: + + micromamba config set ssl_verify /path/to/cacert.pem + +Or set the ``REQUESTS_CA_BUNDLE`` environment variable:: + + export REQUESTS_CA_BUNDLE=/path/to/cacert.pem + +**Disable SSL verification (Not recommended)** + +.. warning:: + + Disabling SSL verification is **not recommended** as it exposes you to security risks including man-in-the-middle attacks. + +Only use this for testing or if you understand the security implications:: + + micromamba config set ssl_verify false + +See `#2857 `_ for more details on corporate proxy environments. diff --git a/libmamba/src/api/configuration.cpp b/libmamba/src/api/configuration.cpp index 9a6510de84..460ec8f745 100644 --- a/libmamba/src/api/configuration.cpp +++ b/libmamba/src/api/configuration.cpp @@ -402,7 +402,11 @@ namespace mamba } else { - if (value.empty() || (value == "true") || (value == "1") || (value == "")) + if (value == "truststore") + { + value = ""; + } + else if (value.empty() || (value == "true") || (value == "1") || (value == "")) { value = ""; } @@ -1561,6 +1565,7 @@ namespace mamba .description("Verify SSL certificates for HTTPS requests") .long_description(unindent(R"( 'ssl_verify' can be either an empty string (regular SSL verification), + the string "truststore" to use the operating system trust store, the string "" to indicate no SSL verification, or a path to a directory with cert files, or a cert file..)")) .needs({ "cacert_path", "offline" }) diff --git a/libmamba/src/download/curl.cpp b/libmamba/src/download/curl.cpp index eb48082f75..4b47c35c4b 100644 --- a/libmamba/src/download/curl.cpp +++ b/libmamba/src/download/curl.cpp @@ -91,6 +91,17 @@ namespace mamba::download { curl_easy_setopt(handle, CURLOPT_PROXY_CAINFO, nullptr); } +#endif + } + else if (ssl_verify == "") + { + // Use OS trust store (Schannel on Windows, system certs on Unix) +#ifdef LIBMAMBA_STATIC_DEPS + curl_easy_setopt(handle, CURLOPT_CAINFO, nullptr); + if (proxy) + { + curl_easy_setopt(handle, CURLOPT_PROXY_CAINFO, nullptr); + } #endif } else diff --git a/libmamba/src/download/downloader.cpp b/libmamba/src/download/downloader.cpp index 85b0e7e240..2cda5d5f66 100644 --- a/libmamba/src/download/downloader.cpp +++ b/libmamba/src/download/downloader.cpp @@ -83,7 +83,8 @@ namespace mamba::download } // TODO: Adapt the semantic of `` to decouple the use of CA certificates // from `conda-forge::ca-certificates` and the system CA certificates. - else if (remote_fetch_params.ssl_verify == "") + else if (remote_fetch_params.ssl_verify == "" + || remote_fetch_params.ssl_verify == "") { // See the location of the CA certificates as distributed by // `conda-forge::ca-certificates`: diff --git a/libmamba/tests/src/core/test_configuration.cpp b/libmamba/tests/src/core/test_configuration.cpp index e4e8a2e8e7..269a8fa55c 100644 --- a/libmamba/tests/src/core/test_configuration.cpp +++ b/libmamba/tests/src/core/test_configuration.cpp @@ -798,6 +798,42 @@ namespace mamba util::unset_env("MAMBA_SSL_VERIFY"); } + TEST_CASE_METHOD(Configuration, "ssl_verify_truststore") + { + // Test basic truststore value + std::string rc = "ssl_verify: truststore"; + load_test_config(rc); + REQUIRE(ctx.remote_fetch_params.ssl_verify == ""); + + // Test quoted truststore value + rc = "ssl_verify: 'truststore'"; + load_test_config(rc); + REQUIRE(ctx.remote_fetch_params.ssl_verify == ""); + + // Test truststore with offline mode - offline should override to false + rc = "ssl_verify: truststore\noffline: true"; + load_test_config(rc); + REQUIRE(ctx.remote_fetch_params.ssl_verify == ""); + + // Reset offline mode + load_test_config("offline: false"); + + // Test truststore with cacert_path - cacert_path should take precedence + rc = "ssl_verify: truststore\ncacert_path: /custom/cert.pem"; + load_test_config(rc); + REQUIRE(ctx.remote_fetch_params.ssl_verify == "/custom/cert.pem"); + + // Reset cacert_path + load_test_config("cacert_path:"); + + // Test environment variable MAMBA_SSL_VERIFY=truststore + util::set_env("MAMBA_SSL_VERIFY", "truststore"); + load_test_config(""); + REQUIRE(ctx.remote_fetch_params.ssl_verify == ""); + + util::unset_env("MAMBA_SSL_VERIFY"); + } + #undef EXPECT_CA_EQUAL TEST_CASE_METHOD(Configuration, "cacert_path") diff --git a/micromamba/src/common_options.cpp b/micromamba/src/common_options.cpp index b1e3ff0e61..6b4d38bc53 100644 --- a/micromamba/src/common_options.cpp +++ b/micromamba/src/common_options.cpp @@ -144,7 +144,7 @@ init_network_options(CLI::App* subcom, Configuration& config) auto& ssl_verify = config.at("ssl_verify"); subcom ->add_option("--ssl-verify", ssl_verify.get_cli_config(), ssl_verify.description()) - ->option_text("'' or PATH") + ->option_text("'', 'truststore', or PATH") ->group(cli_group); auto& ssl_no_revoke = config.at("ssl_no_revoke");