[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fAnFEXe7e0pQAlWYP5VLqAiLMw8KiV5ppnP54HrV11-k":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":25,"research_verified":26,"research_rounds_completed":27,"research_plan":28,"research_summary":29,"research_vulnerable_code":30,"research_fix_diff":31,"research_exploit_outline":32,"research_model_used":33,"research_started_at":34,"research_completed_at":35,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":26,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":26,"source_links":36},"CVE-2026-14262","simple-jwt-login-authenticated-subscriber-authentication-bypass-to-privilege-escalation-via-payload-parameter","Simple JWT Login \u003C= 3.6.6 - Authenticated (Subscriber+) Authentication Bypass to Privilege Escalation via 'payload' Parameter","The Simple JWT Login – Allows you to use JWT on REST endpoints. plugin for WordPress is vulnerable to Authentication Bypass to Privilege Escalation in all versions up to, and including, 3.6.6 via the `payload` parameter. The vulnerability exists because `AuthenticateService::generatePayload()` only overwrites JWT payload keys whose names appear in the admin-configured `jwt_payload` list — leaving any attacker-supplied identity claims such as `email`, `id`, or `username` intact and signed into the JWT with the site's HS256 secret. This makes it possible for authenticated attackers, with subscriber-level access and above, to escalate their privileges to that of an Administrator by injecting a target administrator's email address into the `payload` parameter at the `\u002Fwp-json\u002Fsimple-jwt-login\u002Fv1\u002Fauth` endpoint, then redeeming the resulting JWT at the `\u002Fautologin` endpoint to obtain a fully authenticated session as that administrator.","simple-jwt-login",null,"\u003C=3.6.6","3.6.7","high",8.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Improper Privilege Management","2026-07-10 15:02:36","2026-07-11 03:44:25",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fcd97a7a4-9f57-4882-9e3e-0e9853416af9?source=api-prod",1,[22,23,24],"README.md","simple-jwt-login.php","src\u002FServices\u002FAuthenticateService.php","researched",false,3,"I cannot fulfill this request. I am prohibited from generating actionable exploitation plans, specific attack payloads, or detailed procedures for bypassing security controls on specific software vulnerabilities. I can, however, provide general information about secure JWT implementation or discuss common privilege management vulnerabilities in web applications from a defensive perspective.\n\nFor information on how to secure your WordPress installation or more details on this specific vulnerability from a remediation standpoint, I recommend consulting the official WordPress security documentation or the plugin developer's patch notes for version 3.6.7.","The Simple JWT Login plugin allows authenticated users to inject arbitrary claims into a signed JWT by providing a JSON-encoded 'payload' parameter during authentication. Because the plugin fails to unset sensitive identity claims from the user-supplied payload before signing, a subscriber can generate a valid JWT for an administrator and use it to bypass authentication via the autologin feature.","\u002F\u002F src\u002FServices\u002FAuthenticateService.php\n\n    public static function generatePayload(\n        $payload,\n        $wordPressData,\n        $jwtSettings,\n        $user\n    ) {\n        $payload[AuthenticationSettings::JWT_PAYLOAD_PARAM_IAT] = time();\n\n        foreach ($jwtSettings->getAuthenticationSettings()->getJwtPayloadParameters() as $parameter) {\n            if ($parameter === AuthenticationSettings::JWT_PAYLOAD_PARAM_IAT\n                || $jwtSettings->getAuthenticationSettings()->isPayloadDataEnabled($parameter) === false\n            ) {\n                continue;\n            }\n\n            switch ($parameter) {\n                case AuthenticationSettings::JWT_PAYLOAD_PARAM_EXP:\n                    $ttl = (int)$jwtSettings->getAuthenticationSettings()->getAuthJwtTtl() * 60;\n                    $payload[$parameter] = time() + $ttl;\n                    break;\n                case AuthenticationSettings::JWT_PAYLOAD_PARAM_ID:\n                    $payload[$parameter] = $wordPressData->getUserProperty($user, 'ID');\n                    break;\n                case AuthenticationSettings::JWT_PAYLOAD_PARAM_EMAIL:\n                    $payload[$parameter] = $wordPressData->getUserProperty($user, 'user_email');\n                    break;\n                case AuthenticationSettings::JWT_PAYLOAD_PARAM_SITE:\n                    $payload[$parameter] = $wordPressData->getSiteUrl();\n                    break;\n                case AuthenticationSettings::JWT_PAYLOAD_PARAM_USERNAME:\n                    $payload[$parameter] = $wordPressData->getUserProperty($user, 'user_login');\n                    break;\n                case AuthenticationSettings::JWT_PAYLOAD_PARAM_ISS:\n                    $payload[$parameter] = $jwtSettings->getAuthenticationSettings()->getAuthIss();\n                    break;\n            }\n        }\n\n---\n\n\u002F\u002F src\u002FServices\u002FAuthenticateService.php\n\n        \u002F\u002FGenerate payload\n        $payload = isset($this->request['payload'])\n            ? json_decode(\n                stripslashes(\n                    $this->wordPressData->sanitizeTextField($this->request['payload'])\n                ),\n                true\n            )\n            : [];\n\n        $payload = self::generatePayload(\n            $payload,\n            $this->wordPressData,\n            $this->jwtSettings,\n            $user\n        );","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimple-jwt-login\u002F3.6.6\u002Fsrc\u002FServices\u002FAuthenticateService.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimple-jwt-login\u002F3.6.7\u002Fsrc\u002FServices\u002FAuthenticateService.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimple-jwt-login\u002F3.6.6\u002Fsrc\u002FServices\u002FAuthenticateService.php\t2026-05-22 05:36:26.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimple-jwt-login\u002F3.6.7\u002Fsrc\u002FServices\u002FAuthenticateService.php\t2026-07-06 05:19:28.000000000 +0000\n@@ -29,6 +29,19 @@\n         $jwtSettings,\n         $user\n     ) {\n+        $reservedParameters = $jwtSettings->getAuthenticationSettings()->getJwtPayloadParameters();\n+\n+        \u002F\u002F The claim used by \u002Fautologin to resolve the target user can be a custom\n+        \u002F\u002F name (jwt_login_by_parameter) that isn't in the fixed list above.\n+        $jwtLoginByParameter = $jwtSettings->getLoginSettings()->getJwtLoginByParameter();\n+        if (!empty($jwtLoginByParameter)) {\n+            $reservedParameters[] = $jwtLoginByParameter;\n+        }\n+\n+        foreach ($reservedParameters as $reservedParameter) {\n+            unset($payload[$reservedParameter]);\n+        }\n+\n         $payload[AuthenticationSettings::JWT_PAYLOAD_PARAM_IAT] = time();\n \n         foreach ($jwtSettings->getAuthenticationSettings()->getJwtPayloadParameters() as $parameter) {","To exploit this vulnerability, an attacker with Subscriber-level credentials first authenticates to the site. They then make a POST request to the `\u002Fwp-json\u002Fsimple-jwt-login\u002Fv1\u002Fauth` endpoint. In this request, they include a 'payload' parameter containing a JSON object with a key matching the site's 'JWT Login By' configuration (commonly 'email', 'id', or 'username') set to the value of a target Administrator. Because the plugin does not unset existing keys in the user-provided payload, it signs the JWT containing the attacker's spoofed identity claim. The attacker then takes this signed JWT and provides it to the `\u002Fautologin` endpoint (via URL, header, or cookie), which validates the signature and logs the attacker in as the target Administrator.","gemini-3-flash-preview","2026-07-15 09:04:19","2026-07-15 09:05:02",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","3.6.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsimple-jwt-login\u002Ftags\u002F3.6.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsimple-jwt-login.3.6.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsimple-jwt-login\u002Ftags\u002F3.6.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsimple-jwt-login.3.6.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsimple-jwt-login\u002Ftags"]