Problem
Two_Factor_Core::get_enabled_providers_for_user() assumes _two_factor_enabled_providers is always an array. Malformed legacy/imported/corrupted meta can be scalar or object-shaped; the subsequent array_intersect() then fatals instead of failing closed.
Reproductions
Set _two_factor_enabled_providers to each of the following and call enabled/available provider resolution:
- String provider key
- Integer-backed scalar
- Serialized object /
stdClass
Observed at class-two-factor-core.php around line 671: array_intersect() receives a non-array and throws a TypeError.
Expected
Normalize untrusted persisted meta to a bounded array of provider keys before array operations. Malformed state should not fatal admin lists, profile rendering, CLI, REST, or login. Authentication must remain fail-closed when stored state claims 2FA but cannot resolve safely.
Evidence
Found during an isolated multisite fuzz review of #933:
- Seed:
9338501
- 5,000 randomized provider states
- 500 state transition sequences
- Reproduced consistently for string, numeric scalar, and object values
This appears pre-existing and is separate from #933’s return-path fix.
Problem
Two_Factor_Core::get_enabled_providers_for_user()assumes_two_factor_enabled_providersis always an array. Malformed legacy/imported/corrupted meta can be scalar or object-shaped; the subsequentarray_intersect()then fatals instead of failing closed.Reproductions
Set
_two_factor_enabled_providersto each of the following and call enabled/available provider resolution:stdClassObserved at
class-two-factor-core.phparound line 671:array_intersect()receives a non-array and throws aTypeError.Expected
Normalize untrusted persisted meta to a bounded array of provider keys before array operations. Malformed state should not fatal admin lists, profile rendering, CLI, REST, or login. Authentication must remain fail-closed when stored state claims 2FA but cannot resolve safely.
Evidence
Found during an isolated multisite fuzz review of #933:
9338501This appears pre-existing and is separate from #933’s return-path fix.