Helpdesk and CRM software is where customers describe their problems in plain text, which makes it a data store with an unusually low privacy threshold. Three records published on 19 October 2026 against Frappe applications describe authorisation failures that do not need much sophistication to use: a value trusted from the request, an identifier accepted from the caller, and an endpoint that returns more than the caller asked for. Read together, they map a pattern that is worth checking in any in-house application built on a similar framework.

The three records

  • CVE-2026-111939, Frappe Helpdesk before 1.26.0. Authenticated portal users can create tickets impersonating other customers by supplying a raised_by value. An attacker can call the hd_ticket.api.new endpoint with a victim's email to plant phishing tickets in that customer's portal and read the replies through get_ticket_activities. CVSS v3.1 base score in the record is 4.6, vector AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:L/A:N.

  • CVE-2026-111938, Frappe CRM before 1.74.0. Authenticated Sales Users can modify other users' call logs by supplying arbitrary call_sid values, attaching attacker-written notes and tasks to victims' call logs, leads and deals through add_note_to_call_log and add_task_to_call_log. CVSS v3.1 base score 4.3, vector AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N.

  • CVE-2026-111937, Frappe CRM before 1.81.2. Authenticated Sales Users can access other users' CRM notifications through a missing authorisation check. This entry is part of the same disclosure set and is cited here for completeness; the description is thinner than the other two, so the analysis below leans on the first pair.
    All three are listed as "Deferred" at NVD. The fixes are release-level: 1.26.0 for Helpdesk and 1.74.0 plus 1.81.2 for CRM, which means two of the records were fixed in different CRM releases rather than one.

Failure one: a field that identifies the customer, supplied by the customer

Of the three, CVE-2026-111939 is the one with the most interesting consequences. A ticket creation endpoint needs to know who is raising the ticket. If it takes that identity from the request body, the caller chooses the identity. In a portal with customer-visible content, the result is a two-sided problem: the attacker places text in front of the victim, and the victim's replies become readable to the attacker.
The second half is the part that turns this from an annoyance into an information exposure. Reading replies from a ticket you did not create is a data leak, and the customer's replies will contain exactly what a support conversation tends to contain: order numbers, addresses, fragments of credentials pasted by mistake, and descriptions of internal systems.
The correct implementation does not need a new mechanism. The session already knows who the caller is; the ticket should take
raised_by from the session and ignore any value supplied in the payload. Frameworks make this easy to get wrong because their generic record-creation path accepts a document dictionary and their permission layer evaluates the document as submitted.

Failure two: an identifier that scopes the wrong thing

CVE-2026-111938 is the same mistake with different objects. A call log identified by call_sid is modified by whoever supplies that value. The impact statement is integrity-only, which is consistent with the description: notes and tasks appear on someone else's lead, deal or call record.
A 4.3 is easy to wave through, and the score alone does not explain why this matters. In a sales pipeline, a note attached to a deal is a record of what was said to a customer, so an attacker who can add notes can also create a false record of a conversation, and a team acting on that record will do the wrong thing. The bug is not exfiltration; it is integrity in a decision trail.
The check that fixes it is a lookup: resolve the call log or deal, confirm the caller is a participant, then write. The framework's permission model can do this if the endpoint is written to use it rather than to act on the identifier in the request.

Failure three: a collection that is not scoped to the caller

CVE-2026-111937 is the least specified of the three, and it is also the most common shape in custom applications: a list or detail endpoint for "my notifications" that returns the whole table because the filter was applied in the front end. The description says authenticated Sales Users can access other users' CRM notifications, which is enough to state the class and nothing more.

Why this pattern clusters in this product family

Frappe applications share a metadata-driven model in which doctypes, permissions and endpoints are defined declaratively. That model is genuinely productive, and it also makes object-level authorisation a per-endpoint decision. A REST resource generated from a doctype inherits the doctype's permissions; a custom API method written with @frappe.whitelist() inherits nothing beyond "the caller is logged in".
That is the same distinction security teams already make between function-level and object-level authorisation in any API. The framework does not prevent the correct implementation; it just does not force it, and the default for a new method is the cheaper one.

Verification for operators

  • Version inventory. Helpdesk at 1.26.0 or later, CRM at 1.74.0 or later for the call-log fix and at 1.81.2 or later for the notification fix. Two CRM floors are easy to conflate; the higher one covers both.

  • Endpoint behaviour test. In a staging tenant, authenticate as a low-privilege portal user and attempt both abuse patterns: create a ticket with a different raised_by, and write a note to a call_sid belonging to another user. A fixed build should reject both.

  • Log review. Look for ticket creation events where the creator recorded in the audit trail differs from the raised_by value. Historical exploitation would show as a mismatch, and on an unpatched build that query is worth running once.

  • Custom application review. Any in-house Frappe app with whitelisted methods should be checked for methods that accept an object identifier and act on it without an ownership lookup. That is the generic form of CVE-2026-111938.

  • Notification filters. Confirm that any "my items" list endpoint applies the caller filter server-side. This is testable with two browser sessions.

The part that generalises beyond Frappe

Three records, three different objects, one lesson: an identifier in a request is a claim, not a fact. The claim has to be checked against the session, and the check has to happen on the object the write or read actually targets. Framework documentation rarely states this because it is assumed knowledge; incident write-ups state it because it was not.
For anyone building on a metadata-driven framework, the practical rule is to treat every custom endpoint as an API in a foreign system: authenticate the caller, authorise the object, then act. The framework will not do the second step for a hand-written method, and the advisories above are what that omission looks like when it ships.

Limits

The NVD entries are deferred and the scores above are as recorded, not a measured business impact. This article does not claim exploitation in the wild, does not describe a proof of concept beyond the vendor description, and does not assert that every custom endpoint in these applications is affected. CVE-2026-111937's description is thinner than its siblings, and the analysis marks where it rests on inference rather than a stated mechanism.

References

  • NVD record for CVE-2026-111939: https://nvd.nist.gov/vuln/detail/CVE-2026-111939

  • NVD record for CVE-2026-111938: https://nvd.nist.gov/vuln/detail/CVE-2026-111938

  • NVD record for CVE-2026-111937: https://nvd.nist.gov/vuln/detail/CVE-2026-111937

  • Frappe Helpdesk advisory GHSA-xf93-jjcj-44vm: https://github.com/frappe/helpdesk/security/advisories/GHSA-xf93-jjcj-44vm

  • Frappe CRM advisory GHSA-843p-qp2f-p2v8: https://github.com/frappe/crm/security/advisories/GHSA-843p-qp2f-p2v8

  • Frappe Helpdesk release v1.26.0: https://github.com/frappe/helpdesk/releases/tag/v1.26.0

  • Frappe CRM release v1.74.0: https://github.com/frappe/crm/releases/tag/v1.74.0