OTA Password Retention In ESP8266 Core 3.0.0 Firmware Migration
0 reputation · 22 Jul 2026, 06:19 UTC
0 reputation · 22 Jul 2026, 06:19 UTC
The Arduino OTA authentication model stores password credentials in device flash memory, where they persist across resets and firmware updates. A precise design question emerges regarding how these credentials behave when the ESP8266 core version transitions, such as from 2.7.4 to 3.0.0, which altered the OTA handshake and may require password re-entry. The goal is to characterize whether stored passwords are retained, silently rejected, or demand explicit reconfiguration across version boundaries, and whether any implicit expiry mechanism exists.
Constraints include the absence of a built-in credential expiry flag, the default 'admin' password used when no password is set, and limited flash write endurance that discourages frequent credential resets. Version-specific changes in the OTA protocol are documented across core releases, but the exact interaction between stored passwords and new handshake expectations remains unresolved.
How does the ArduinoOTA library reconcile a previously stored password with a core version that expects a different handshake format? Does migration always require password re-entry, or can a legacy password be accepted without modification? What is the practical impact on device security when the default 'admin' credential persists across firmware updates without user intervention?
The stored OTA password from ESP8266 Arduino Core 2.x is not retained when migrating to Core 3.0.0. The legacy password cannot be reconciled with the new handshake format, and migration always requires explicit password re-entry in the 3.0.0 sketch. The default "admin" credential does not persist across the version boundary; in 3.0.0, OTA authentication is disabled unless ArduinoOTA.setPassword() is called in the new firmware.
Core 2.x (NONOS SDK) stored the OTA password in a dedicated 4 KB configuration sector at the end of the sketch flash area. Core 3.0.0 (ESP8266_RTOS_SDK/FreeRTOS) introduces a new partition table that does not map or preserve this sector. When a 3.0.0 firmware is flashed—whether via serial or a 2.x OTA update—the legacy config sector is either unmapped, overwritten, or ignored by the new OTA implementation (esp_ota_ops).
The password hash format and challenge-response flow differ fundamentally. A 2.x password hash (including one set via setPasswordHash()) is not portable to 3.0.0.
ArduinoOTA.setPassword("newpass"), that credential becomes active immediately.setPassword(), the OTA service starts without authentication—the string "admin" has no special meaning in 3.0.0 unless explicitly set.A device updated from 2.x to 3.0.0 without an explicit setPassword() in the new sketch will accept unauthenticated OTA connections. This window persists until the next OTA or serial upload that includes a password. There is no implicit credential expiry mechanism in either core version; credentials only disappear when the config sector is erased (full flash erase, partition table change, or explicit sector wipe).
# 1. Confirm 2.x password works
# Flash 2.7.4 sketch with ArduinoOTA.setPassword("test123")
# Verify OTA auth succeeds with "test123"
# 2. Flash 3.0.0 sketch WITH setPassword("test123") via serial (no flash erase)
# Verify OTA still accepts "test123"
# 3. Flash 3.0.0 sketch WITHOUT setPassword()
# Observe OTA requires no password → confirms no legacy retention
# 4. Inspect config sector (optional)
esptool.py read_flash 0xFC000 0x1000 config_2x.bin # typical 1 MB flash, last 4 KB
# Compare before/after 3.0.0 flash to see sector fateAre you using a custom partition table (CSV) that defines an "ota_config" or "nvs" partition intended to survive core upgrades? The standard Arduino IDE board definitions for 3.0.0 do not include such a partition. If a custom table preserves a compatible sector, the behavior may differ—please confirm your partition scheme.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.