{"id":"CVE-2026-104014","kind":"vulnerability","aliases":["CVE-2026-104014"],"related":[],"title":"WordPress OTP plugin lets anyone reset any account password","description":"The Naimur Email OTP Verification for WooCommerce plugin for WordPress is vulnerable to authentication bypass in versions up to, and including, 2.1.0. This is due to the plugin's password-reset finalization endpoint (the wp_ajax_nopriv_ceovw_update_new_password action handled by CEOVW_AJAX::update_new_password()) authorizing the reset solely by the presence of a database row marking an email as 'VERIFIED', with no timestamp check, no session binding, and no per-reset token — combined with mark_otp_as_verified_for_reset() leaving the row in that state after a user enters their code (abandoning the flow leaves the row behind), and a scheduled 'ceovw_cleanup_expired_otps_event' cron that has no add_action() handler anywhere in the plugin so cleanup never runs. This makes it possible for unauthenticated attackers to take over any account whose owner previously requested and verified a password-reset code and did not immediately finish choosing a new password — the attacker needs only the victim's email address and a nonce that the plugin itself localizes publicly into the CEOVW_APP global on the WooCommerce account page for logged-out visitors, after which they call the endpoint, overwrite the victim's password, and are returned a live wordpress_logged_in_ session cookie for that user (full site takeover if the account is an administrator).","summary":"The Naimur Email OTP Verification for WooCommerce plugin, up to and including 2.1.0, lets an unauthenticated visitor finish a password reset for a victim's email once that victim has verified a reset code and not finished choosing a new password. The attacker gets a logged-in session cookie for that account, which is full site control if the account is an administrator.","severity":"critical","cvss":9.8,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"naimur-email-otp-for-woocommerce","fixed":["2.1.1"],"affected":"<= 2.1.0","ecosystem":"wordpress"}],"ecosystems":[],"tags":["account-takeover","auth-bypass","package","woocommerce","wordpress","wp-plugin"],"not_affected_if":["plugin-2.1.1-or-newer","plugin-newer-than-2.1.0","plugin-not-installed"],"how_to_check":"In WordPress admin > Plugins, check the Naimur Email OTP Verification for WooCommerce version (slug naimur-email-otp-for-woocommerce); 2.1.0 or lower is affected. WP-CLI: wp plugin get naimur-email-otp-for-woocommerce --field=version. After updating, consider resetting passwords of admin accounts that started a password reset recently and watch for unexpected password changes or logins.","fix":"Update the plugin to 2.1.1 or later (current wordpress.org release is 2.1.2). 2.1.1 was tagged 2026-11-02 as 'security fix for password reset'.","status":"open","published_at":"2026-11-07T12:17:41+00:00","first_seen_at":"2026-11-07T12:47:07+00:00","triaged_at":"2026-11-07T12:48:35+00:00","updated_at":"2026-11-07T12:50:06+00:00","category":"package","confidence":0.85,"triage":{"at":"2026-11-07T12:48:35Z","model":"claude-haiku-5-5","output":{"fix":"unknown","reach":"internet","title":"WordPress OTP plugin lets anyone reset any account password","impact":"high","summary":"The Naimur Email OTP Verification for WooCommerce plugin, up to and including 2.1.0, lets an unauthenticated visitor finish a password reset for a victim's email once that victim has verified a reset code and not finished choosing a new password. The attacker gets a logged-in session cookie for that account, which is full site control if the account is an administrator.","audience":"businesses","category":"package","nicknames":[],"who_cares":["wordpress","woocommerce","wp-plugin"],"confidence":0.8,"fix_status":"unknown","needs_auth":"no","worst_case":"Attacker takes over any account, including administrators, and gets a live session","analyst_note":"Check the WordPress plugin repository or the NVD entry for a fixed version after 2.1.0 and whether the vendor has released a patch.","how_to_check":"- Check the installed version of the Naimur Email OTP Verification for WooCommerce plugin in the WordPress admin plugins list; versions up to and including `2.1.0` are affected.\n- Look for the `ceovw_update_new_password` AJAX action or the `CEOVW_AJAX` class in the plugin files.","plain_action":"","needs_analyst":true,"not_affected_if":["plugin-not-installed","plugin-newer-than-2.1.0"],"who_is_affected":"Sites running the Naimur Email OTP Verification for WooCommerce plugin version 2.1.0 or earlier, which adds email OTP to WooCommerce password resets. Exposure depends on that plugin being active; sites without it are not affected. The sources do not say whether any configuration avoids the flaw.","user_interaction":"no","needs_special_setup":"unknown","severity_if_unknown":"critical"},"cost_usd":0.000776,"input_tokens":4584,"output_tokens":636,"severity_before":"critical"},"analyst_status":"done","analyst_note":"Check the WordPress plugin repository or the NVD entry for a fixed version after 2.1.0 and whether the vendor has released a patch.","search":"'-104014':12A,15A '-2026':11A,14A '2.1.0':46B,119C 'abandon':197C 'account':8A,23B,86B,94B,238C,285C,321C 'account-takeov':22B 'action':140C,217C 'add':216C 'address':267C 'administr':97B,324C 'ajax':134C,144C 'anyon':5A 'anywher':219C 'app':280C 'attack':76B,233C,260C 'auth':26B 'auth-bypass':25B 'authent':111C 'author':148C 'behind':203C 'bind':170C 'bypass':27B,112C 'call':295C 'ceovw':136C,143C,207C,279C 'check':167C 'choos':71B,255C 'cleanup':208C,224C 'code':67B,196C,249C 'combin':177C 'control':91B 'cooki':83B,312C 'cron':212C 'cve':10A,13A 'databas':157C 'due':122C 'email':18A,36B,59B,100C,161C,266C 'endpoint':131C,297C 'enter':194C 'event':211C 'expir':209C 'final':130C 'finish':51B,70B,254C 'flow':199C 'for':20A 'full':89B,316C 'get':77B 'global':281C 'handl':141C 'handler':218C 'immedi':253C 'includ':45B,118C 'leav':185C,200C 'let':4A,47B 'live':307C 'local':275C 'log':80B,289C,309C 'logged-in':79B 'logged-out':288C 'make':228C 'mark':159C,179C 'naimur':17A,35B,99C 'naimur-email-otp-for-woocommerce':16A 'need':261C 'never':225C 'new':73B,138C,146C,257C 'nonc':270C 'nopriv':135C 'otp':2A,19A,37B,101C,180C,210C 'overwrit':298C 'owner':240C 'packag':28B 'page':286C 'password':9A,53B,74B,128C,139C,147C,247C,258C,302C 'password-reset':127C,246C 'per':174C 'per-reset':173C 'plugin':3A,33B,41B,105C,125C,222C,273C 'possibl':230C 'presenc':154C 'previous':241C 'public':276C 'request':242C 'reset':6A,54B,66B,129C,150C,175C,184C,248C 'return':305C 'row':158C,187C,202C 'run':226C 'schedul':206C 'session':82B,169C,311C 'site':90B,317C 'sole':151C 'state':190C 'take':235C 'takeov':24B,318C 'timestamp':166C 'token':176C 'unauthent':49B,232C 'updat':137C,145C 'user':193C,315C 'verif':38B,102C 'verifi':64B,163C,182C,244C 'version':114C 'victim':57B,62B,264C,300C 'visitor':50B,291C 'vulner':109C 'whose':239C 'woocommerc':29B,40B,104C,284C 'woocommerce':21A 'wordpress':1A,30B,107C,308C 'wp':32B,133C 'wp-plugin':31B","nicknames":[],"mitigations":[],"who_affected":"Sites running the Naimur Email OTP Verification for WooCommerce plugin version 2.1.0 or earlier, which adds email OTP to WooCommerce password resets. Exposure depends on that plugin being active; sites without it are not affected. The sources do not say whether any configuration avoids the flaw.","tier":"B","verified":{"fix":{"at":"2026-11-07T12:50:06Z","by":"analyst","doc":"https://plugin-repo.wpbeacon.io/wporg/naimur-email-otp-for-woocommerce/src/tag/v2.1.1/includes","run_id":2108}},"analyst_revisit_at":null,"fix_status":"available","audience":"businesses","plain_action":null,"pkeys":["naimuremailotpforwoocommerce"],"ptokens":["email","for","naimur","otp","woocommerce"],"labels":["accounttakeover","authbypass","critical","package","woocommerce","wordpress","wpplugin"],"campaign_type":null,"search_a":"'-104014':12A,15A '-2026':11A,14A 'account':8A 'anyon':5A 'cve':10A,13A 'email':18A 'for':20A 'let':4A 'naimur':17A 'naimur-email-otp-for-woocommerce':16A 'otp':2A,19A 'password':9A 'plugin':3A 'reset':6A 'woocommerce':21A 'wordpress':1A","search_b":"'2.1.0':46B 'account':23B,86B,94B 'account-takeov':22B 'administr':97B 'attack':76B 'auth':26B 'auth-bypass':25B 'bypass':27B 'choos':71B 'code':67B 'control':91B 'cooki':83B 'email':36B,59B 'finish':51B,70B 'full':89B 'get':77B 'includ':45B 'let':47B 'log':80B 'logged-in':79B 'naimur':35B 'new':73B 'otp':37B 'packag':28B 'password':53B,74B 'plugin':33B,41B 'reset':54B,66B 'session':82B 'site':90B 'takeov':24B 'unauthent':49B 'verif':38B 'verifi':64B 'victim':57B,62B 'visitor':50B 'woocommerc':29B,40B 'wordpress':30B 'wp':32B 'wp-plugin':31B","search_c":"'2.1.0':119C 'abandon':197C 'account':238C,285C,321C 'action':140C,217C 'add':216C 'address':267C 'administr':324C 'ajax':134C,144C 'anywher':219C 'app':280C 'attack':233C,260C 'authent':111C 'author':148C 'behind':203C 'bind':170C 'bypass':112C 'call':295C 'ceovw':136C,143C,207C,279C 'check':167C 'choos':255C 'cleanup':208C,224C 'code':196C,249C 'combin':177C 'cooki':312C 'cron':212C 'databas':157C 'due':122C 'email':100C,161C,266C 'endpoint':131C,297C 'enter':194C 'event':211C 'expir':209C 'final':130C 'finish':254C 'flow':199C 'full':316C 'global':281C 'handl':141C 'handler':218C 'immedi':253C 'includ':118C 'leav':185C,200C 'live':307C 'local':275C 'log':289C,309C 'logged-out':288C 'make':228C 'mark':159C,179C 'naimur':99C 'need':261C 'never':225C 'new':138C,146C,257C 'nonc':270C 'nopriv':135C 'otp':101C,180C,210C 'overwrit':298C 'owner':240C 'page':286C 'password':128C,139C,147C,247C,258C,302C 'password-reset':127C,246C 'per':174C 'per-reset':173C 'plugin':105C,125C,222C,273C 'possibl':230C 'presenc':154C 'previous':241C 'public':276C 'request':242C 'reset':129C,150C,175C,184C,248C 'return':305C 'row':158C,187C,202C 'run':226C 'schedul':206C 'session':169C,311C 'site':317C 'sole':151C 'state':190C 'take':235C 'takeov':318C 'timestamp':166C 'token':176C 'unauthent':232C 'updat':137C,145C 'user':193C,315C 'verif':102C 'verifi':163C,182C,244C 'version':114C 'victim':264C,300C 'visitor':291C 'vulner':109C 'whose':239C 'woocommerc':104C,284C 'wordpress':107C,308C 'wp':133C","first_public_at":"2026-11-07T12:17:41+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","cvss_by":"security@wordfence.com","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-104014","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-104014","severity":null,"published_at":"2026-11-07T12:17:41+00:00","modified_at":"2026-11-07T12:17:41+00:00","first_seen_at":"2026-11-07T12:47:07+00:00","fetched_at":"2026-11-07T12:47:07+00:00","note":null},{"source":"analyst","external_id":"CVE-2026-104014:2108","url":"https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/naimur-email-otp-for-woocommerce/naimur-email-otp-verification-for-woocommerce-210-unauthenticated-authentication-bypass-to-account-takeover-via-abandoned-password-reset-finalization","severity":null,"published_at":"2026-11-07T12:50:06+00:00","modified_at":"2026-11-07T12:50:06+00:00","first_seen_at":"2026-11-07T12:50:06+00:00","fetched_at":"2026-11-07T12:50:06+00:00","note":"Wordfence advisory (researcher s4m0y3d) says patched in 2.1.1; plugin mirror shows maintainer commit 'Release 2.1.1: security fix for password reset' dated 2026-11-02; wp.org page shows 2.1.2 current and describes single-use reset authorization. No exploitation or PoC seen; ~40 active installs. Only fix verified (maintainer commit/page); affected range from Wordfence/NVD.","cites":["https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/naimur-email-otp-for-woocommerce/naimur-email-otp-verification-for-woocommerce-210-unauthenticated-authentication-bypass-to-account-takeover-via-abandoned-password-reset-finalization","https://wordpress.org/plugins/naimur-email-otp-for-woocommerce/","https://plugin-repo.wpbeacon.io/wporg/naimur-email-otp-for-woocommerce/src/tag/v2.1.1/includes"]}],"documents":[{"id":95547,"url":"https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/naimur-email-otp-for-woocommerce/naimur-email-otp-verification-for-woocommerce-210-unauthenticated-authentication-bypass-to-account-takeover-via-abandoned-password-reset-finalization","title":"Wordfence: Naimur Email OTP <= 2.1.0 auth bypass","kind":"advisory","source":"analyst","publisher":null,"text":null,"published_at":null,"relation":"advisory","confidence":null,"note":null},{"id":95548,"url":"https://wordpress.org/plugins/naimur-email-otp-for-woocommerce/","title":"Naimur Email OTP Verification for WooCommerce (wordpress.org)","kind":"vendor","source":"analyst","publisher":null,"text":null,"published_at":null,"relation":"fix","confidence":null,"note":null},{"id":95549,"url":"https://plugin-repo.wpbeacon.io/wporg/naimur-email-otp-for-woocommerce/src/tag/v2.1.1/includes","title":"Plugin mirror: v2.1.1 'security fix for password reset'","kind":"release","source":"analyst","publisher":null,"text":null,"published_at":null,"relation":"fix","confidence":null,"note":null}],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}