Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-52887

CVE-2026-52887: NocoBase SQL Injection Vulnerability

CVE-2026-52887 is a SQL injection flaw in NocoBase that allows authenticated users to execute stacked PostgreSQL statements. This post covers the technical details, affected versions, impact, and mitigation steps.

Published:

CVE-2026-52887 Overview

CVE-2026-52887 is a SQL injection vulnerability in NocoBase, an AI-powered no-code/low-code platform for building business applications. The flaw exists in the @nocobase/plugin-notification-in-app-message plugin prior to version 2.0.61. The GET /api/myInAppChannels:list endpoint passes the filter[latestMsgReceiveTimestamp][$lt] parameter into a Sequelize.literal() template string without escaping or parameter binding. Any authenticated user can inject stacked PostgreSQL statements and achieve command execution using COPY ... TO PROGRAM. The issue is tracked as [CWE-89] and fixed in NocoBase 2.0.61.

Critical Impact

Authenticated attackers can execute arbitrary PostgreSQL statements and operating system commands on the database server, resulting in full compromise of application data and the underlying host.

Affected Products

  • NocoBase versions prior to 2.0.61
  • @nocobase/plugin-notification-in-app-message plugin
  • Deployments backed by PostgreSQL

Discovery Timeline

  • 2026-07-15 - CVE-2026-52887 published to NVD
  • 2026-07-16 - Last updated in NVD database

Technical Details for CVE-2026-52887

Vulnerability Analysis

The vulnerability resides in packages/plugins/@nocobase/plugin-notification-in-app-message/src/server/defineMyInAppChannels.ts. The server-side handler for listing in-app message channels accepted a client-controlled latestMsgReceiveTimestamp.$lt filter and interpolated it directly into a Sequelize.literal() fragment. Because Sequelize.literal() emits raw SQL, any injected content is executed by PostgreSQL without sanitization.

Exploitation requires only a signed-up authenticated account, which is often obtainable via self-registration in NocoBase deployments. Stacked statements allow the attacker to move beyond data exfiltration and invoke PostgreSQL's COPY ... TO PROGRAM, which spawns operating system processes under the database service account. This escalates a SQL injection into remote command execution on the database host.

Root Cause

The root cause is missing input validation and unsafe SQL construction. The handler did not verify that $lt was a numeric timestamp before embedding it into a literal SQL expression, violating the principle of parameterized queries.

Attack Vector

An authenticated attacker sends a crafted GET /api/myInAppChannels:list request where the filter[latestMsgReceiveTimestamp][$lt] value contains a closing SQL fragment followed by additional PostgreSQL statements. Because the value is concatenated into raw SQL, PostgreSQL executes the appended statements, including calls to COPY ... TO PROGRAM 'command' for command execution.

typescript
// Patch from packages/plugins/@nocobase/plugin-notification-in-app-message/src/server/defineMyInAppChannels.ts
import { ChannelsCollectionDefinition as ChannelsDefinition } from '@nocobase/plugin-notification-manager';
import { InAppMessagesDefinition as MessagesDefinition } from '../types';

function parseLatestMsgReceiveTimestampLt(filter: unknown) {
  const latestMsgReceiveTimestamp =
    typeof filter === 'object' && filter !== null
      ? (filter as { latestMsgReceiveTimestamp?: unknown }).latestMsgReceiveTimestamp
      : null;
  if (
    typeof latestMsgReceiveTimestamp !== 'object' ||
    latestMsgReceiveTimestamp === null ||
    !Object.prototype.hasOwnProperty.call(latestMsgReceiveTimestamp, '$lt')
  ) {
    return null;
  }

  const value = (latestMsgReceiveTimestamp as { $lt?: unknown }).$lt;
  if (typeof value === 'string' && value.trim() === '') {
    throw new Error('Invalid latest message receive timestamp filter');
  }
  if (typeof value !== 'number' && typeof value !== 'string') {
    throw new Error('Invalid latest message receive timestamp filter');
  }

  const timestamp = Number(value);
  if (!Number.isFinite(timestamp)) {
    throw new Error('Invalid latest message receive timestamp filter');
  }

  return timestamp;
}

Source: GitHub Commit 68d64e3. The fix coerces the $lt value to a finite number and rejects any non-numeric input before it reaches SQL construction.

Detection Methods for CVE-2026-52887

Indicators of Compromise

  • Requests to /api/myInAppChannels:list containing SQL keywords such as COPY, ;, --, SELECT, or pg_ inside the filter[latestMsgReceiveTimestamp][$lt] parameter.
  • PostgreSQL logs showing COPY ... TO PROGRAM statements originating from the NocoBase application user.
  • Unexpected child processes spawned by the postgres service, especially shells, curl, wget, or scripting interpreters.
  • New or unexpected authenticated user registrations followed shortly by traffic to the in-app channels endpoint.

Detection Strategies

  • Enable PostgreSQL statement logging (log_statement = 'all') on non-production tiers and alert on COPY TO PROGRAM usage.
  • Deploy a web application firewall rule that inspects the filter query parameter for stacked statement patterns and PostgreSQL metacharacters.
  • Correlate NocoBase access logs with database process telemetry to identify SQL injection followed by command execution.

Monitoring Recommendations

  • Monitor outbound network connections from the database host that do not match its baseline behavior.
  • Track file writes and process launches performed by the PostgreSQL service account.
  • Audit newly created NocoBase accounts and their API activity within the first hour of registration.

How to Mitigate CVE-2026-52887

Immediate Actions Required

  • Upgrade NocoBase to version 2.0.61 or later, which contains the validated timestamp parser.
  • Disable public self-registration on NocoBase until the upgrade is complete to reduce the attacker pool.
  • Revoke the PostgreSQL superuser role from the NocoBase database account and restrict COPY ... TO PROGRAM privileges.
  • Review audit logs for prior exploitation attempts against /api/myInAppChannels:list.

Patch Information

The vulnerability is fixed in NocoBase v2.0.61 via commit 68d64e3fcfb8be2ae4f3bfc9e1ee3f85b87c89ce. Full technical detail is available in the GitHub Security Advisory GHSA-p849-8hwh-84j9.

Workarounds

  • Run NocoBase behind a reverse proxy that rejects requests to /api/myInAppChannels:list where the filter parameter contains characters outside the digit and dot set for the $lt value.
  • Restrict the database role used by NocoBase so it cannot execute COPY TO PROGRAM or other filesystem-touching functions.
  • Enforce network egress filtering from the database host to limit the impact of successful command execution.
bash
# Upgrade NocoBase and constrain the database role
npm install @nocobase/[email protected]

# In psql, revoke risky privileges from the NocoBase role
REVOKE pg_execute_server_program FROM nocobase_app;
REVOKE pg_read_server_files      FROM nocobase_app;
REVOKE pg_write_server_files     FROM nocobase_app;

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.