CVE-2026-89426: Knit Pay <= 9.6.1.0 - Authenticated (Subscriber+) Privilege Escalation via Gravity Forms Role Field
The Knit Pay – Cashfree, Instamojo, Razorpay, PayPal and more plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 9.6.1.0. This is due to the maybeupdateuserrole() function reading the target role directly from an attacker-controlled Gravity Forms entry field — configured via the feed's userrolefieldid — and passing it to WPUser::setrole() without validating the supplied value against an allowlist of permitted roles. This makes it possible for authenticated attackers, with Subscriber-level access and above, to elevate their privileges to administrator by tampering with the hidden role field value at form submission time. Exploitation is further enabled by the fact that $0 orders are synchronously marked as SUCCESS during form submission without requiring a real payment, and when no GF User Registration user can be resolved, the role assignment target falls back to $lead['createdby'] — the currently authenticated submitter's own user ID — making any authenticated form submitter an eligible exploitation target.
Affected Software
Event History
Frequently Asked Questions
Who is exposed to exploitation?
WordPress sites using an affected Knit Pay version with a Gravity Forms feed that uses the user_role_field_id setting are exposed. Any authenticated user with Subscriber-level access or higher can be an exploitation target.
What does an attacker need to do?
The attacker needs an authenticated WordPress account and access to submit the relevant Gravity Forms form. They can tamper with the hidden role field during submission to supply an administrator role value.
Is a real payment required to exploit the issue?
No. Orders with a $0 value are synchronously marked SUCCESS during form submission, so exploitation does not require completing a real payment.
Why can the attacker elevate their own account?
If no Gravity Forms User Registration user is resolved, the role assignment falls back to the entry's created_by value. This is the currently authenticated form submitter's user ID, allowing the submitted role to be applied to that user's own account.