From 493db0c2bb750a2fced3fadad0d0aabb0f0c87e9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Oct 2026 02:45:19 -1000 Subject: [PATCH] [esp32] Add allow_insecure_tls() for components that skip certificate verification (#20506) --- esphome/components/esp32/__init__.py | 11 +++++++++++ esphome/components/http_request/__init__.py | 10 ++-------- esphome/components/nextion/display.py | 5 +---- tests/component_tests/esp32/test_esp32.py | 18 ++++++++++++++++++ 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 9bceaf5676d..422413a269f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -2071,6 +2071,17 @@ def require_vfs_termios() -> None: CORE.data[KEY_VFS_TERMIOS_REQUIRED] = True +def allow_insecure_tls() -> None: + """Let esp-tls connect without verifying the server certificate. + + The two sdkconfig flags are global, so a component asking for an unverified + connection switches them on for the whole build; they are never switched off + here because another component may have asked first. + """ + add_idf_sdkconfig_option("CONFIG_ESP_TLS_INSECURE", True) + add_idf_sdkconfig_option("CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", True) + + def require_certificate_bundle() -> None: """Enable the mbedTLS root certificate bundle for this build. diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index ad51d5f39be..a2c181a5ae0 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -226,14 +226,8 @@ async def to_code(config: ConfigType) -> None: # use_full_certificate_bundle: true esp32.require_certificate_bundle() - esp32.add_idf_sdkconfig_option( - "CONFIG_ESP_TLS_INSECURE", - not config.get(CONF_VERIFY_SSL), - ) - esp32.add_idf_sdkconfig_option( - "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", - not config.get(CONF_VERIFY_SSL), - ) + else: + esp32.allow_insecure_tls() if CORE.is_esp8266: cg.add_library("ESP8266HTTPClient", None) if CORE.is_rp2 and CORE.using_arduino: diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 3a70be21caf..983a4777e81 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -261,10 +261,7 @@ async def to_code(config): if CORE.is_esp32: esp32.request_http_client() - esp32.add_idf_sdkconfig_option("CONFIG_ESP_TLS_INSECURE", True) - esp32.add_idf_sdkconfig_option( - "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", True - ) + esp32.allow_insecure_tls() elif CORE.is_esp8266: cg.add_library("ESP8266HTTPClient", None) diff --git a/tests/component_tests/esp32/test_esp32.py b/tests/component_tests/esp32/test_esp32.py index 9072a906293..bb751dd677c 100644 --- a/tests/component_tests/esp32/test_esp32.py +++ b/tests/component_tests/esp32/test_esp32.py @@ -30,6 +30,7 @@ from esphome.components.esp32 import ( _reconcile_network_sdkconfig, _reconcile_vfs_fatfs_sdkconfig, _user_sdkconfig_wants_tls, + allow_insecure_tls, ) from esphome.components.esp32.const import ( KEY_ESP32, @@ -2400,3 +2401,20 @@ def test_nvs_cache_in_psram_explicit_true_on_valid_board_is_quiet( sdkconfig = CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] assert sdkconfig.get("CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM") is True assert "nvs_cache_in_psram" not in caplog.text + + +def test_allow_insecure_tls_only_switches_the_flags_on( + set_core_config: SetCoreConfigCallable, +) -> None: + """A component that verifies certificates must not undo another one's request.""" + set_core_config(PlatformFramework.ESP32_IDF) + CORE.data[KEY_ESP32] = {KEY_SDKCONFIG_OPTIONS: {}} + + allow_insecure_tls() + # A second caller, or a verifying component that no longer touches the flags, leaves them on + allow_insecure_tls() + + assert CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] == { + "CONFIG_ESP_TLS_INSECURE": True, + "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY": True, + }