CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-23643
5.40.04%

CakePHP Pagination: Turning 'Next Page' into 'Next Pwn'

Alon Barad
Alon Barad
Software Engineer

Feb 17, 2026·5 min read·11 visits

PoC Available

Executive Summary (TL;DR)

CakePHP's `PaginatorHelper::limitControl()` failed to sanitize query parameter keys when generating hidden input fields to preserve state. By crafting a URL with a malicious parameter name (e.g., `?"> <script>...=1`), an attacker can execute arbitrary JavaScript in the victim's browser. Patched in 5.2.12 and 5.3.1 via strict escaping and integer casting.

A classic tale of 'helpful' framework magic going rogue. The CakePHP PaginatorHelper, in its noble quest to preserve your search filters across pages, inadvertently created a mechanism to reflect malicious HTML via query parameter keys. This Reflected Cross-Site Scripting (XSS) vulnerability affects versions 5.2.10 through 5.3.0, allowing attackers to inject arbitrary JavaScript into the victim's session by simply convincing them to click a link with a malformed query string key.

The Hook: The Road to Hell is Paved with Good Intentions

Pagination is arguably the most boring part of web development. Nobody wakes up excited to write OFFSET and LIMIT SQL clauses. That is why we use frameworks like CakePHP. They handle the drudgery. Specifically, the PaginatorHelper is the unsung hero that renders those "Previous | 1 | 2 | 3 | Next" links and the "Items per page" dropdowns.

But here is the catch: Pagination needs to be stateful. If you search for "users named Steve" and then click "Page 2", the application needs to remember you were searching for "Steve". If it forgets, Page 2 just lists everyone, which defeats the purpose.

To solve this, CakePHP's limitControl() method (which renders the "items per page" dropdown) does something very helpful. It looks at your current URL query parameters (like ?q=Steve&sort=id) and automatically generates hidden HTML input fields for them inside the limit control form. This ensures that when you change the limit from 20 to 50, you don't lose your search context. It's a feature, not a bug... until it becomes a bug.

The Flaw: Trusting the Key

Developers are trained—beaten, really—into sanitizing values. If we see $_GET['username'], we instinctively reach for sanitization functions before echoing it out. We assume the value is the dirty part. But what about the key?

In PHP, $_GET is an associative array. It has keys and values. The vulnerability in CVE-2026-23643 exists because the generateHiddenFields method inside PaginatorHelper iterated through the query data and trusted the keys. It took the parameter name and shoved it directly into the name attribute of a hidden input field.

Here is the logic flaw: The code assumed that while values might be malicious, parameter names would be safe. But the HTTP protocol doesn't care. You can send a request where the parameter name is an entire JavaScript payload. When CakePHP echoed that key back to the browser to "preserve state," it unknowingly preserved an XSS payload.

The Code: Anatomy of a Screw-up

Let's look at the crime scene in src/View/Helper/PaginatorHelper.php. The function generateHiddenFields is responsible for the recursion through the query data.

The Vulnerable Code:

// BEFORE: Blindly trusting $key ($fieldName)
foreach ($data as $key => $value) {
    $fieldName = $prefix ? $prefix . '[' . $key . ']' : $key;
    if (is_array($value)) {
        $out .= $this->generateHiddenFields($value, $fieldName);
    } else {
        // OOPS: $fieldName is injected directly into the HTML attribute
        $out .= $this->Form->hidden($fieldName, ['value' => $value]);
    }
}

If $fieldName contains "><script>alert(1)</script>, the Form->hidden() helper generates: <input type="hidden" name=""><script>alert(1)</script>" value="...">

The Fix:

The patch is embarrassingly simple, as most XSS fixes are. They wrapped the $fieldName in the h() function (CakePHP's shortcut for htmlspecialchars).

// AFTER: Sanitizing the key
- $out .= $this->Form->hidden($fieldName, ['value' => $value]);
+ $out .= $this->Form->hidden(h($fieldName), ['value' => $value]);

They also added a secondary check. The limit parameter itself, which controls how many items are shown, is now explicitly cast to an integer. This kills a secondary vector where the value of the limit itself could have been manipulated.

'value' => $limit !== null ? (int)$limit : null,

The Exploit: Breaking Out

To exploit this, we don't need fancy headers or race conditions. We just need a browser and a lack of shame. We need to target a page that uses $this->Paginator->limitControl(). This is common in index views/tables.

The Attack Vector:

  1. Recon: Find a paginated list (e.g., /products/index).

  2. Payload Construction: We need to break out of the name="..." attribute. The payload will look like this as a query parameter: ?"><img src=x onerror=alert(document.domain)>=1

  3. Execution: The application receives the request. The PaginatorHelper sees a parameter key of "><img src=x onerror=alert(document.domain)> with a value of 1. It tries to create a hidden field for it.

  4. Resulting HTML:

    <form method="get" ...>
      <!-- ... other fields ... -->
      <input type="hidden" name=""><img src=x onerror=alert(document.domain)>" value="1">
    </form>

The browser renders the input, sees the closing quote `

The Impact: Why Panic?

It is "only" Reflected XSS, right? In the hierarchy of vulnerabilities, it sits below RCE and SQLi. However, context is king.

CakePHP is a framework often used to build internal business tools, CRMs, and administrative panels—the kind of apps where users have elevated privileges. If an attacker can trick an administrator into clicking a link (via a phishing email claiming "Urgent: Check these paginated logs"), the script executes in the admin's session.

From there, the attacker can:

  • Hijack the Session: Steal the CAKEPHP session cookie.
  • Perform Actions: Use JavaScript to force the browser to make POST requests (CSRF) to create new admin users or delete data.
  • Deface: Change the page content to sow chaos.

Because this vulnerability resides in a core helper used globally across the application, every paginated page in the application potentially becomes an attack vector.

The Fix: Upgrade or Patch

If you are running CakePHP 5.2.10 through 5.3.0, you are vulnerable. The fix was released on January 14, 2026.

Primary Mitigation: Run the magic words:

composer update cakephp/cakephp

Ensure you land on 5.2.12 or 5.3.1 (or higher).

Manual Mitigation: If you are stuck on a legacy version and can't upgrade the core (you poor soul), you shouldn't be editing vendor/ files directly. However, you can extend the PaginatorHelper in your src/View/Helper directory, override limitControl, and ensure you aren't passing unescaped data. But honestly? Just upgrade. It's Composer. It usually works. Usually.

Official Patches

CakePHPRelease notes for version 5.2.12 containing the fix

Fix Analysis (2)

Technical Appendix

CVSS Score
5.4/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
EPSS Probability
0.04%
Top 87% most exploited

Affected Systems

CakePHP Framework

Affected Versions Detail

Product
Affected Versions
Fixed Version
CakePHP
Cake Software Foundation
>= 5.2.10, < 5.2.125.2.12
CakePHP
Cake Software Foundation
5.3.05.3.1
AttributeDetail
CWE IDCWE-79 (Cross-site Scripting)
CVSS v3.15.4 (Medium)
Attack VectorNetwork (Reflected via Query String)
ImpactSession Hijacking, DOM Manipulation
EPSS Score0.00043 (Low Probability)
Exploit StatusNo Public Weaponized Exploit
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1185Browser Session Hijacking
Collection
CWE-79
Reflected Cross-site Scripting

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Known Exploits & Detection

Manual AnalysisExploit involves crafting a query parameter where the key contains an HTML breakout sequence.
NucleiDetection Template Available

Vulnerability Timeline

Vulnerability reported via GitHub Issue #19172
2026-01-08
Partial fix (integer casting) committed
2026-01-12
Complete fix (key escaping) committed
2026-01-14
CakePHP 5.2.12 and 5.3.1 released
2026-01-14
CVE-2026-23643 Published
2026-01-16

References & Sources

  • [1]GitHub Security Advisory
  • [2]CakePHP Bakery Release Announcement

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.