# Wi-Fi management-frame security update plan Initial review date: **2026-09-16**; integration status updated **2026-09-18**. The original review was a focused documentation-only follow-up to [dependency advisory coverage](dependency_advisory_coverage.md#new-release-note-finding-wi-fi-management-frame-corruption). **At that initial review, no correction was implemented, exploit reproduced, build run, device accessed, or upgrade approved.** The fix-bearing complete IDF 5.5.3 vendor bundle is now integrated in the validated candidate; this is not radio-hardware vulnerability closure or deployment approval. See [current integration evidence](idf_candidate_integration.md#final-integration-evidence--2026-09-18) and [semantic rebase review](idf_553_rebase_review.md). ## Decision **Prefer a complete, immutable Espressif IDF 5.5 maintenance-release bundle, integrated through a compatible pinned PlatformIO package/toolchain, over transplanting Wi-Fi archives into IDF 5.5.0.** IDF **5.5.3 is the verified fix-bearing reference candidate/minimum demonstrated release here**, not a recommendation to deploy it in preference to all later maintenance releases. The earlier coverage records 5.5.4/5.5.5; selecting a newer deployment candidate requires the same immutable provenance and compatibility gates below, not a repeat broad advisory audit. Do not change PMF/WPA3 policy as an automatic mitigation. Do not replace only `libnet80211.a`, edit only a callback declaration, relax source guards, or overwrite the installed SDK. The vendor correction is integrated in the fresh candidate build; deployed old firmware remains exposed, and target/radio validation remains pending. PMF/WPA3 has not been weakened. ## Current applicability and trigger limits Rechecked authoritative source `src/wifi_manager.c:315–363`: - SoftAP uses `WIFI_AUTH_WPA2_WPA3_PSK`, four clients, `pmf_cfg.capable=true`, `required=false`, `WPA3_SAE_PWE_BOTH`. AP/APSTA are real supported paths, including live fallback transitions (`set_runtime_ap_enabled`). Optional PMF is **not PMF disabled**. - Station uses PMF capability in both profiles; mixed has WPA2 minimum/optional PMF, WPA3 requires PMF. Do not downgrade station profiles to address a demonstrated SoftAP trigger. - Existing generated `sdkconfig.h` identifies ESP32-S3 and enables SoftAP, WPA3 SAE, SoftAP SAE, SAE H2E and SAE-PK support. This is build metadata, not proof of a running device's current mode or negotiated association. - Architecture: the permanent Wi-Fi manager owns driver operations and bounded events; application NVS is authoritative, driver storage is RAM-only, AP policy is off/fallback/always. Working edits require explicit save. Preserve manager ownership, secret wiping and secret-free status. UART0 recovery and native USB UART1 access must remain independent of network success. Broker single-writer/multiple-isolated-observer behavior is unchanged. The official contained fix says that when the supplicant sends an **authentication response for an already-connected station, with keys installed after a successful four-way handshake**, management encryption was selected from `bss->pmf_enable` without checking whether the frame was robust. The encryption code assumed header space that had not been allocated, causing memory corruption. The fix checks robust-management-frame status before encryption. This supports a current-feature exposure candidate when SoftAP is active with the relevant station/key/PMF state. Radio delivery of the relevant management exchange, rather than application HTTPS/SSH authentication, is the pertinent access path (inference from the described Wi-Fi operation). The public text does **not** establish whether an attacker must know the PSK, personally complete association, or can spoof an existing station's exchange. It supplies no packet-level proof, CVSS, reliable arbitrary-code-execution claim, or exhaustive affected-mode matrix. Do not characterize this as proven unauthenticated remote exploitation, nor assume application login protects it. STA-only exclusion is limited to the described AP-response path, not a blanket clean bill for the opaque bundle. The same vendor change also fixes an RSN-IE length/allocation mismatch, deauthentication-reason parsing, and default SAE PWE values. The project's short configured IE set has not been shown to trigger the allocation issue; do not conflate that uncertainty with the established old ABI/bundle identity. ## Official immutable provenance Official sources fetched in this review: 1. [5.5.3 release](https://github.com/espressif/esp-idf/releases/tag/v5.5.3), also [release API](https://api.github.com/repos/espressif/esp-idf/releases/tags/v5.5.3): explicitly names the management-frame memory-corruption correction under `a3927641`. 2. [Merge commit](https://github.com/espressif/esp-idf/commit/a3927641bfd0aedfaab3514cba3d7fb01378ce4d), checked through its official commit API: **`a3927641bfd0aedfaab3514cba3d7fb01378ce4d`**. Its title emphasizes SAE defaults; the title alone omits the security detail. 3. [Contained fix patch](https://github.com/espressif/esp-idf/commit/caf4cad3b422be5c2f93afeff4cd07796a262b46.patch): **`caf4cad3b422be5c2f93afeff4cd07796a262b46`**, “Backport some wifi fixes,” with the trigger explanation. This is the merge's second parent, not a conflicting identification. 4. [Annotated release tag object](https://api.github.com/repos/espressif/esp-idf/git/tags/b31fcc7a314a44ad992b58f589f7d1d8a4fadff6): tag object **`b31fcc7a314a44ad992b58f589f7d1d8a4fadff6`** resolves to IDF commit **`2c211b236707889e8400c4dc5644dd5c4ee071e0`**. [Immutable comparison](https://api.github.com/repos/espressif/esp-idf/compare/a3927641bfd0aedfaab3514cba3d7fb01378ce4d...2c211b236707889e8400c4dc5644dd5c4ee071e0) reports ahead 195 / behind 0, establishing inclusion of the merge. ### Exact published source/ABI delta The fix changes four paths: | Path relative to IDF | Published change | | --- | --- | | `components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h` | `wpa_funcs.wpa_ap_get_wpa_ie`: `uint8_t *(*)(uint8_t *len)` becomes `uint8_t *(*)(size_t *len)` | | `components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c` | Matching callback implementation takes `size_t *ie_len`; assignment from `hapd->wpa_auth->wpa_ie_len` remains | | `components/esp_wifi/lib` | Submodule `d7373a90dc3f0be841b29911e33de5f99988dbff` → **`a4e903fe43bf09a95022f9802db43d39740ccc0b`** | | `components/esp_wifi/include/esp_wifi_types_generic.h` | Two SAE PWE documentation comments record default `WPA3_SAE_PWE_BOTH`; not structure-layout changes | The historical shared IDF 5.5.0 header and callback take `uint8_t *`; `esp_wpa_main.c` registers the callback for SoftAP. The callback slot/pointer size need not change for this to be an ABI break: the width and interpretation of the pointed-to output change (one byte versus a `size_t`, four bytes on ESP32-S3). Mixed old/new caller and callee can corrupt storage or leave an incorrect length. Casting the callback does not fix the contract. Both sides, including the opaque caller, must agree. The visible C edits are the length correction/interface marker. **The management-encryption fix is in the vendor binary update, not a public C hunk that can be copied into this application.** ### Bundle identity: baseline, fix point, release point are different - Historical shared installed baseline matches Wi-Fi submodule **`8a1b7bbc00e895d040c5c9a6fb9d1db2bbfc7958`** from IDF v5.5, not the fix's immediate predecessor `d7373a90…`. - The exact fix-point bundle is **`a4e903fe43bf09a95022f9802db43d39740ccc0b`**. - The complete 5.5.3 release points to **`e0befaa593277b4e80726079fbd521b4681754c2`**, verified again at the immutable release commit. [Wi-Fi comparison](https://api.github.com/repos/espressif/esp32-wifi-lib/compare/a4e903fe43bf09a95022f9802db43d39740ccc0b...e0befaa593277b4e80726079fbd521b4681754c2) reports ahead 3 / behind 0. Do not call the fix-point bundle the final 5.5.3 bundle. Calculated Git blob SHA-1 (`blob \0` plus bytes) of **all seven installed S3 archives** and compared against official metadata for [baseline](https://api.github.com/repos/espressif/esp32-wifi-lib/contents/esp32s3?ref=8a1b7bbc00e895d040c5c9a6fb9d1db2bbfc7958), [fix point](https://api.github.com/repos/espressif/esp32-wifi-lib/contents/esp32s3?ref=a4e903fe43bf09a95022f9802db43d39740ccc0b), and [release point](https://api.github.com/repos/espressif/esp32-wifi-lib/contents/esp32s3?ref=e0befaa593277b4e80726079fbd521b4681754c2): | Archive | Installed = baseline Git blob | Fix-point Git blob | 5.5.3-release Git blob | | --- | --- | --- | --- | | `libcore.a` | `ec2e76caad4c29ee92ec45432e0dc3bf946ea4c7` | `af63b0f8254bde084b2f474cdba1c1d63b4ae750` | `9f7b14a8bf6eec64973da8adc65d35b5ba9bee49` | | `libespnow.a` | `d4925dc7f73173077e8ed58abbbe5a59b5bb7be5` | `da0537c3f754a9d638fbecd4f4d806bfa66316b4` | `132b4f67e339ca2081d2add91c14eefa39476ff9` | | `libmesh.a` | `5cd43bf5a0a0388fb6f093a154401f00227d9570` | `6ae30c90ba59ab949e98db89b6b51daab434a5a0` | `2e9dc1c8c7afbf033337b4175032e9b1161e3262` | | `libnet80211.a` | `6ee20bec142638dc0a442b9642de9fa62db6ddd0` | `8ce8a2a6a9a753e31508bd609bf0a0d1d44c332f` | `2800d447ec385d33869373696ba8191292647694` | | `libpp.a` | `c9fc98fe529c9ff2891839fdb9a41b1189c03c49` | `536fd25e30a1be76ff122d93e7481f1da22e6892` | `8944bcad7371621045f376cf74c62fde6f368cbb` | | `libsmartconfig.a` | `31518eb9336f07de14b4a71c0389217a54ed3ec7` | `19e8274e0961fdf88351a0dec6e0d696b8ee2b94` | `4dc759e25617aa00b9e12887fd092a1d5780a170` | | `libwapi.a` | `0604ff76aa9134b475daf08496e03350d5ef8f09` | `e43863a22e93990b8a4deb7c4efc8e4c27566789` | `65655b6feab0572a6e8a1200946d53a21f3f4722` | All historical shared-SDK archives matched baseline; all differ from both newer bundles. This is artifact identity, not proof that every archive is linked or contains the defect. Remote binaries were **not downloaded during the initial review**. Later candidate archive download/verification and complete Wi-Fi/PHY/coexistence/supplicant package comparisons are recorded in the integration/rebase reviews; the candidate uses the release-point column, not this old baseline. Git IDs are provenance identifiers, not independently measured remote SHA-256 digests or a vendor signature verification. The release API advertises the submodule-inclusive `esp-idf-v5.5.3.zip`, asset ID **357881088**, SHA-256 **`d16e6b57b1df1a523aff6a1d0ef2f99cf058cb71e73f694429769eaaea171428`**. This is vendor-published metadata, not a locally verified download. The release is marked `immutable=false`; therefore pin the resolved commit/submodules and verify artifact hashes, not merely a tag URL. Espressif warns that GitHub's automatic source archives omit submodules; those are not complete SDK inputs. ## PMF/WPA3 mitigation assessment Both the [v5.5 documentation source](https://raw.githubusercontent.com/espressif/esp-idf/v5.5/docs/en/api-guides/wifi-security.rst) and [immutable candidate documentation](https://raw.githubusercontent.com/espressif/esp-idf/2c211b236707889e8400c4dc5644dd5c4ee071e0/docs/en/api-guides/wifi-security.rst), plus the installed type header, establish: - `pmf_cfg.capable` is deprecated, effectively true internally. Setting it false is **not a supported PMF-off mitigation**. - `required=false` permits optional PMF; it does not disable it. - `esp_wifi_disable_pmf_config()` is the documented optional-PMF disable API. Disabling PMF on WPA3 or WPA2/WPA3 mixed SoftAP returns an error. - WPA3 mandates PMF. WPA2-only mode by itself still does not prove PMF is disabled. **No issue-specific official workaround was found in the inspected release/fix text.** The API documentation explains general configuration, not an endorsement that disabling PMF safely mitigates all defects in this change. The trigger supplies a rationale that actually eliminating `bss->pmf_enable` could avoid the described encryption path; the opaque implementation and lifecycle have not been proved to honor that invariant across existing associations/restarts. Consequently, a WPA2-only plus explicit PMF-disable implementation is at most an **unapproved conditional workaround candidate**. It would remove SAE benefits and management-frame protection, require explicit owner acceptance, documented threat trade-offs, correct manager-owned stop/reconfigure/start sequencing, checked API results, and target evidence that negotiated PMF cannot reappear across APSTA/fallback transitions. It would not repair the RSN-IE allocation defect. Do not implement it as a silent downgrade, global WPA3 Kconfig removal, or station-profile change. If operational containment is urgently required before an update, the owner may explicitly choose existing AP-off policy (removes the described AP response path) or Wi-Fi-off (removes radio service), accepting lost network/fallback access. These are feature-withdrawal containment options, **not vendor-certified workarounds or a source fix**. Preserve and verify UART0/native USB access first; do not automatically persist policy changes. No containment action was taken here. ## What a coherent replacement entails ### Preferred: complete vendor maintenance release Use all IDF source, private/public headers, Wi-Fi/PHY/coexistence libraries and other submodules from one resolved release, with its toolchain and Python/build requirements. Do not install final-release blobs alongside fix-point-only C edits or mix two release revisions. Preserve the application security policies separately through audited overrides. Current integration disposition (supplied parent evidence, 2026-09-18): | Input | Current state | Remaining boundary | | --- | --- | --- | | Root `platformio.ini` | Platform 6.13.0, framework 3.50503.0 / IDF 5.5.3, Xtensa and RISC-V 14.2.0+20251107 | Exact version pins, not complete immutable root dependency closure; default root build timed out during installation at 200 seconds before compilation | | Isolated `app-validated` | Fresh build PASS; 95,552 B RAM / 1,749,493 B flash (+1,212 / −19,408 B versus historical 94,340 / 1,768,901 B) | Linked size is not runtime reserve | | Protected corrections | Nine C sources plus forced header; per-entry semantic rebase, five new signed WS receive checks; 982 cases / 10 mutation checks | No original correction removed as superseded; retain exact fail-closed guards | | Actual build/host validation | Explicit candidate SDK/core/build with interop and web performance PASS 24/24; source equality 3,237 files, identical pre/post hash recorded in [validation](phase9_validation.md#current-candidate-execution--2026-09-18) | Not radio-hardware vulnerability closure or full target acceptance | | Radio delivery | All packaged Wi-Fi/PHY/coexistence/supplicant files match locked framework archive; candidate callback is `size_t *` | Not independent opaque-code correctness or recursive upstream submodule provenance | | Notices | Nine entries semantically rebased, 66 unchanged, 75 total; 36 fixtures PASS; two actual bundles each 77 files / 4,433,930 bytes | Recipient/source/legal clearance pending | The completed [semantic rebase review](idf_553_rebase_review.md#3-per-entry-semantic-disposition) covers candidate originals, not only Wi-Fi: HTTPS cleanup/private-key release, HTTPD scratch/null-read handling, server-local TLS policy, DHCP bounds, TLS EMS failure, X.509 allocation failure; retain/revalidate wolfSSH password/parser/ordering/ABI changes and wolfCrypt settings. Mark each correction **retained, rebased, or superseded with source/test evidence**. Upstream fixes do not automatically supersede local lifetime/policy additions in the same source. Also retain silent-panic/no-coredump and heap-wipe policy guards. The durable architecture's older four-correction summary is not the complete current inventory; the current generator and code map are authoritative. ### Contingency: vendor-supported backport onto 5.5.0 The smallest **published delta against the fix's own parent** is the four-path change above. The smallest **proven safe delta against this project's 5.5.0** is **not established**. A candidate backport must at least pair both callback changes with one complete ESP32-S3 Wi-Fi archive set from the same vendor revision, retain the vendor patch/provenance, and establish compatibility with all private Wi-Fi headers, OS adapter tables, supplicant structures/callbacks, PHY/coexistence interfaces, configuration ABI and toolchain. All seven S3 archives form the conservative replacement set; do not mix old optional archives with new ones simply because current linking omits them. This minimum set is necessary for coherent provenance, **not sufficient proof** of cross-baseline compatibility. Ask Espressif for a supported 5.5.0 backport bundle or an explicit compatibility statement with its required source/header/library/toolchain prerequisites, confirming both management-frame and IE-length corrections. The immediate-parent blob pointer differs from baseline; successful linking alone cannot establish binary layout/calling-contract compatibility. Without that evidence or a complete audited dependency closure, choose the full-release path rather than treating the two C signature edits plus blobs as approved. ## Implementation plan history and remaining acceptance Steps 1–4 below preserve the original plan: package selection, isolated preparation, override rebase and fresh candidate build/host checks now have the evidence above. Complete immutable dependency closure is not claimed. Steps 5–6 remain acceptance/release gates; historical “no code change yet” language is not a new blocker. 1. **Compatibility/provenance gate first, no code change yet.** Resolve one deployment release and PlatformIO delivery combination. Record immutable SDK commit, recursive submodule pins, package/toolchain identities and SHA-256 manifests. Confirm vendor inclusion of the fix. Obtain missing packaging/ABI evidence; if unavailable, report the blocker instead of guessing a framework URL or transplanting archives. 2. **Prepare isolated inputs after approval.** Do not modify the user's shared installed SDK. Obtain complete vendor inputs in a dedicated location, verify provenance/hashes, and compare only relevant integration surfaces and protected-source entries. Keep existing managed components pinned where compatible; explicitly review any resolver-required changes. Review license/notice/source-delivery updates for new radio/SDK artifacts. 3. **Rebase security contracts.** Implement a reviewed per-entry disposition and exact new source pins, retain fail-closed guards, and verify every generated override/forced header reaches the actual targets. Add a bundle-consistency check for the selected SDK and archive identities so an old/new mixed bundle fails deterministically. Do not enable unrelated features, regenerate web assets, migrate credentials, or alter partitions. 4. **Build/host gates in the later implementation task only.** Clean candidate build with the selected toolchain; inspect linked archive paths/map, generated configuration and actual compilation inputs. Run SDK override, crypto, parser, ordering/interop, authentication/protocol, build-policy and notice validations as applicable to the resolved input changes. Record sizes and compare resource budgets; a host pass is not radio validation. Existing historical passes do not validate this candidate. 5. **Target gates under explicit device authorization.** Exercise WPA2 with/without negotiated PMF and WPA3 SoftAP; authenticate/reassociate after keys are installed; cover PMF optional/required behavior, four clients, disconnect/reconnect and AP/STA/APSTA/fallback transitions. Obtain vendor regression guidance or an authorized isolated-radio reproduction for the exact trigger; ordinary reconnect tests alone do not prove vulnerability closure. Stress concurrent HTTPS/WebSocket/SSH and verify bounded recovery, heap/stack reserve, queue behavior, no secret/crash-memory disclosure, and unchanged broker isolation. Verify UART0 recovery and native USB UART1 operation while Wi-Fi fails/stops/restarts. Include persisted-config reboot tests without erasure. 6. **Release gate.** Keep PMF/WPA3 security at least unchanged. Record exact artifacts and test evidence, retain a controlled recovery image and configuration backup procedure, and mark the old image as still exposed rather than calling rollback a security fix. No flash erase, upload, pin changes or deployment until separately authorized. Update durable project memory only when implemented contracts/ownership genuinely change. ## Open evidence and review boundary - **Resolved:** official fix IDs/description; exact visible ABI delta; all seven installed S3 archives match baseline; distinct fix and final-release bundles; release/fix ancestry; current application configuration; PMF-disable restrictions; exact-IDF/hash guards; recommended versus installed toolchain mismatch. - **Current resolved integration:** official PlatformIO 6.13.0 / IDF 5.5.3 delivery and exact toolchain selection, semantic override rebase, fresh candidate build and 24/24 host validation, whole packaged radio-component equality and notice rebase. - **Still unresolved:** complete immutable ancillary/tool/Python/managed dependency closure; independent PHY/coexistence upstream submodule provenance; opaque binary implementation correctness; packet-level attacker requirements; target/runtime/resource evidence and deployment acceptance. A 5.5.0 transplant remains unproved and was not selected. - A follow-up GitHub API request for candidate `components/esp_phy/lib` returned **HTTP 403 rate limit exceeded**. The sequential metadata query stopped there, so PHY/coexistence pins were not established; no inference was drawn from that failure. Already completed Wi-Fi/release/ancestry queries succeeded. Official raw documentation remained available. Do not treat this partial metadata boundary as a compatibility clearance. - Historical initial-review validation only: read-only local source/package/config inspection; local seven-archive Git-blob hashing; official patch/release/tag/content/comparison/toolchain/documentation reads. No broad repeated dependency audit, binary download, PlatformIO invocation, build, test suite, device operation, configuration edit, or asset generation. Documentation links/provenance do not constitute signed-vendor attestation, exhaustive security certification, or Phase 9 sign-off.