Nov 2, 2026·9 min read·4 visits
DBHub versions prior to 0.22.6 fail to enforce MySQL and MariaDB whitespace requirements for single-line '--' comments in the read-only SQL validator. Attackers or compromised AI agents can append stacked DDL or DML statements after a non-whitespace '--' sequence (e.g., 'SELECT 1--1;DROP TABLE victim') to execute unauthorized database modifications.
An interpretation conflict in Bytebase DBHub (< 0.22.6) allows attackers to bypass read-only SQL query restrictions when connected to MySQL or MariaDB instances. Because DBHub's custom SQL tokenizer treats any '--' sequence as a comment, whereas MySQL and MariaDB require trailing whitespace or a control character, crafted queries containing '--' immediately followed by non-whitespace characters allow stacked destructive SQL statements to execute on connections configured as read-only.
Bytebase DBHub (@bytebase/dbhub) is an open-source database bridge and tool engine designed to connect external applications, AI assistants, and Model Context Protocol (MCP) database agents to backend relational databases. To safely expose database inspection capabilities to automated agents and untrusted inputs, DBHub implements an application-layer read-only mode. This mode inspects incoming SQL query batches to verify that only non-mutating statements (such as SELECT or EXPLAIN) are executed against the underlying database.
In versions prior to 0.22.6, a lexer discrepancy exists between DBHub's internal SQL parser (src/utils/sql-parser.ts) and the downstream command processors of MySQL and MariaDB. This vulnerability is classified under CWE-436 (Interpretation Conflict) and CWE-863 (Incorrect Authorization). The internal tokenizer unconditionally treats any occurrence of two consecutive hyphens (--) as the start of a single-line comment, whereas MySQL and MariaDB lexers require -- to be followed by whitespace, a control character, or the end of the input.
Because the DBHub MySQL and MariaDB connectors initialize their database connection pools with multipleStatements: true and transmit the raw, unparsed SQL string to the database engine after validation, an attacker can smuggle secondary SQL statements inside a sequence that DBHub views as a comment. When the database server processes the raw query, it evaluates the -- sequence as arithmetic unary minus operators and executes the subsequent semicolon-delimited statements.
This flaw allows an unauthenticated attacker—either interacting directly with a DBHub tool endpoint or operating via indirect prompt injection against an AI agent—to bypass the isReadOnlySQL check. Consequently, the attacker can execute arbitrary Data Manipulation Language (DML) and Data Definition Language (DDL) statements, resulting in unauthorized data modification or destruction.
The root cause of GHSA-j656-3hf2-fvjc is an architectural mismatch between how DBHub validates SQL statements and how it dispatches them to the database driver, combined with an incomplete dialect implementation in the custom SQL tokenizer. When DBHub receives a query execution request in src/tools/execute-sql.ts, the validation pipeline passes the raw SQL string into splitSQLStatements to break the batch into individual statements based on semicolon delimiters outside of string literals and comments.
Each resulting statement is passed to isReadOnlySQL(statement, connectorType), which verifies that the query begins with an allowed read-only keyword and does not contain forbidden mutating tokens. Crucially, if every statement produced by splitSQLStatements passes this check, DBHub does not reconstruct or execute the sanitized statement array. Instead, the connector passes the original, unmodified SQL string directly to the database driver.
In ANSI SQL and PostgreSQL, -- unconditionally initiates a single-line comment that extends to the next newline character (\n) or end of input. However, the MySQL and MariaDB SQL specifications deviate from ANSI SQL to avoid conflicts with arithmetic negation and decrement patterns. In MySQL and MariaDB, -- only initiates a comment if the character immediately following the second dash satisfies my_isspace() or my_iscntrl()—specifically ASCII bytes <= 0x20 (spaces, tabs, newlines, control characters) or 0x7F (ASCII DEL), or if the second dash is at the end of the query.
Prior to version 0.22.6, DBHub's scanSingleLineComment function in src/utils/sql-parser.ts checked solely for sql[i] === "-" && sql[i + 1] === "-". When presented with a token such as --1, DBHub entered comment-scanning mode and consumed all subsequent characters on the line, including any semicolon statement terminators. Meanwhile, the downstream MySQL or MariaDB lexer parsed --1 as - (-1), remained in normal command-parsing mode, recognized the semicolon as a statement boundary, and executed the subsequent statement.
In versions prior to 0.22.6, the MySQL tokenizer (scanTokenMySQL) in src/utils/sql-parser.ts delegated comment scanning to the generic scanSingleLineComment function. This function lacked awareness of dialect-specific lexical rules:
// Vulnerable implementation in src/utils/sql-parser.ts (< 0.22.6)
function scanSingleLineComment(sql: string, i: number): SQLToken | null {
if (sql[i] !== "-" || sql[i + 1] !== "-") { return null; }
let j = i;
// Consumes everything until newline, ignoring the character at sql[i + 2]
while (j < sql.length && sql[j] !== "\n") { j++; }
return { type: TokenType.Comment, end: j };
}In commit 872bb338f7d31f6afe517a076ac3e3edafaaaf08 (Pull Request #342), the maintainers remediated the parser inconsistency by introducing a dialect-specific scanner, scanSingleLineCommentMySQL, and wiring it into scanTokenMySQL. This function inspects the byte at sql[i + 2] and rejects the comment token if the character is a printable non-whitespace character:
// Patched implementation in src/utils/sql-parser.ts (0.22.6)
function scanSingleLineCommentMySQL(sql: string, i: number): SQLToken | null {
if (sql[i] !== "-" || sql[i + 1] !== "-") { return null; }
const next = sql[i + 2];
// Comment trigger = whitespace, control char, or EOL. MySQL's lexer uses
// my_isspace() || my_iscntrl(), so besides bytes <= 0x20 this also includes
// ASCII DEL (0x7F). Anything else means the dashes are minus operators.
if (next !== undefined && next.charCodeAt(0) > 0x20 && next.charCodeAt(0) !== 0x7f) {
return null;
}
let j = i;
while (j < sql.length && sql[j] !== "\n") { j++; }
return { type: TokenType.Comment, end: j };
}In addition to correcting the lexical analysis, the patch introduced an engine-level defense-in-depth mechanism in src/connectors/mysql/index.ts and src/connectors/mariadb/index.ts. When options.readonly is enabled, the connector wraps query execution inside an explicit read-only transaction:
// Defense-in-depth transaction wrapper in src/connectors/mysql/index.ts
if (options.readonly) {
await conn.query("START TRANSACTION READ ONLY");
}
// ... execute target SQL batch ...
if (options.readonly) {
await conn.query("COMMIT");
}> [!NOTE]
> Assessing fix completeness: While START TRANSACTION READ ONLY causes the database engine to reject DML modifications (INSERT, UPDATE, DELETE), MySQL and MariaDB execute an implicit commit before running most DDL statements (such as DROP TABLE or ALTER TABLE), which terminates the read-only transaction context. Therefore, preventing DDL execution continues to rely entirely on the accuracy of the userland tokenizer in src/utils/sql-parser.ts so long as multipleStatements: true remains enabled on the database connection pool.
Exploiting this vulnerability requires access to a DBHub query execution interface connected to a MySQL or MariaDB backend with read-only mode enabled. Because DBHub is designed to serve as an MCP tool server for Large Language Models (LLMs), exploitation can occur either through direct API invocation by an authorized client or indirectly via prompt injection against an AI agent that has permission to invoke the execute-sql tool.
To construct a bypass payload, the attacker begins with a benign SELECT statement followed by an integer or expression, immediately appends -- followed by a numeric digit (such as 1), adds a semicolon delimiter, and appends the target mutating SQL statement on the same line:
SELECT 1--1;DROP TABLE victimWhen this payload is processed by a vulnerable version of DBHub (< 0.22.6), the execution flow proceeds through the following steps:
splitSQLStatements("SELECT 1--1;DROP TABLE victim", "mysql") scans SELECT 1 as standard SQL tokens.--1;DROP TABLE victim), scanSingleLineComment classifies the remainder of the string as TokenType.Comment and strips it from the output.splitSQLStatements returns a single-element array containing ["SELECT 1"].isReadOnlySQL evaluates "SELECT 1", confirms it matches the allowed keyword list for MySQL, and returns true.conn.query("SELECT 1--1;DROP TABLE victim") on a connection pool configured with multipleStatements: true.SELECT 1 - (-1) (returning 2), encounters the semicolon statement terminator, and executes DROP TABLE victim.The same mechanism allows arbitrary data modification or exfiltration preparation via stacked INSERT, UPDATE, or GRANT statements, provided the database user configured in the DBHub connection string possesses the underlying database privileges.
The primary impact of GHSA-j656-3hf2-fvjc is the complete bypass of application-layer read-only enforcement for MySQL and MariaDB connections. In deployments where administrators rely on DBHub's --readonly flag while configuring the underlying database connection with a privileged MySQL/MariaDB database account, an attacker gains the ability to modify or destroy data up to the privilege ceiling of the database account.
The vulnerability is rated with a CVSS v4 base score of 6.1 (Medium) with the vector CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N. The vector reflects a network-accessible attack surface (AV:N) with low attack complexity (AC:L), requiring specific deployment conditions (AT:P, such as MySQL/MariaDB backends and read-only reliance) and passive user or agent interaction (UI:P) in prompt-injection scenarios.
Confidentiality impact is rated as None (VC:N) because the read-only mode already permits arbitrary SELECT queries by design; the bypass does not grant read access beyond what is already exposed. However, both Integrity (VI:H) and Availability (VA:H) impacts on the vulnerable system are High, as attackers can modify arbitrary records via UPDATE/DELETE or destroy database schemas via DROP TABLE and TRUNCATE.
Administrators and developers using @bytebase/dbhub must upgrade to version 0.22.6 or later. Version 0.22.6 updates the SQL tokenizer to align with MySQL and MariaDB lexical rules (scanSingleLineCommentMySQL) and wraps read-only queries in START TRANSACTION READ ONLY blocks.
If immediate upgrading is not possible, organizations should enforce read-only constraints at the database authentication layer rather than relying on DBHub's application-layer SQL parser. Specifically, configure DBHub to connect to MySQL or MariaDB using a dedicated database user that has been granted only SELECT and SHOW VIEW privileges, revoking all INSERT, UPDATE, DELETE, DROP, ALTER, and CREATE permissions.
Security teams should also audit application and database query logs for historical exploitation attempts. Queries matching the regular expression --[^\s\x00-\x20\x7F].*; indicate sequences where double dashes are followed immediately by printable characters and a statement terminator, which is a strong indicator of an attempt to smuggle stacked SQL statements past the read-only filter.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@bytebase/dbhub Bytebase | < 0.22.6 | 0.22.6 |
| Attribute | Detail |
|---|---|
| Vulnerability ID | GHSA-j656-3hf2-fvjc |
| Affected Package | @bytebase/dbhub (< 0.22.6) |
| Primary CWE | CWE-436 (Interpretation Conflict) |
| Secondary CWE | CWE-863 (Incorrect Authorization) |
| CVSS v4 Score | 6.1 (Medium) |
| Attack Vector | Network (SQL Query / Prompt Injection) |
| Impact | Read-Only Bypass (Arbitrary DDL/DML Execution) |
| Exploit Status | Proof-of-Concept Documented |
The product processes structured data using two components (the DBHub custom SQL parser and the downstream MySQL/MariaDB database server lexer) that interpret single-line comment delimiters ('--') inconsistently.
CVE-2026-62374 (GHSA-f9j6-8p6x-r9j6) is a verification bypass vulnerability in the OpenWallet Foundation SD JWT JS library (@sd-jwt/core and @sd-jwt/decode versions 0.19.0 and earlier). Due to permissive UTF-8 decoding and the omission of mandatory reference checks during presentation verification, tampered or unreferenced disclosures are silently dropped rather than rejected. This deviates from RFC 9901 §7.1 requirements and allows attackers to execute silent claim-set reduction attacks against relying parties.
CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.
CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.
CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).
CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.
An algorithmic complexity vulnerability (CWE-407) in pyasn1 versions prior to 0.6.5 allows unauthenticated attackers to cause a Denial of Service (DoS) via crafted ASN.1 payloads. The flaw resides in the binary-encoded ASN.1 REAL mantissa deserialization routine within RealPayloadDecoder.valueDecoder. By performing iterative byte-string slicing and repeated bitwise shifts on a growing arbitrary-precision integer, the decoder exhibits quadratic time and memory allocation complexity relative to the mantissa length. Supplying a BER-, CER-, or DER-encoded payload with a large REAL mantissa causes excessive CPU consumption and blocks application worker processes.