Skip to content

fix(xugudb): escape SQL identifiers and literals in metadata/DDL paths (#1914)#2175

Open
HandSonic wants to merge 7 commits into
OtterMind:mainfrom
HandSonic:fix/sqli-xugudb
Open

fix(xugudb): escape SQL identifiers and literals in metadata/DDL paths (#1914)#2175
HandSonic wants to merge 7 commits into
OtterMind:mainfrom
HandSonic:fix/sqli-xugudb

Conversation

@HandSonic

@HandSonic HandSonic commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Related issue

Part of the SQL-injection hardening tracked in #1914 (multi-plugin effort; this PR covers XuguDB). Prior art: #2052 (Oracle escapeSqlLiteral), #2053 (SQL Server identifier quoting).

Summary

These are second-order injection paths: values such as table/schema/view/index names originate from the connected database's own metadata, so exploitation requires a maliciously named object in a target database. The fix is still worthwhile hardening and matches the pattern already merged for Oracle and SQL Server.

What changed:

  • New XugudbSqlEscapes helper:
    • escapeSqlLiteral — neutralizes values interpolated into single-quoted SQL string literals (single-quote doubling).
    • quoteIdentifier/escapeIdentifier — strips one surrounding quote pair and doubles every embedded double quote (") for quoted-identifier positions.
  • Applied across metadata/DDL SQL-building sites in 7 files (see diff).
  • Notable: SET SCHEMA TO %s and DROP TABLE IF EXISTS %s previously had no quotes — now quoted + escaped.
  • XUGUDBSqlBuilder now overrides quoteIdentifier/quoteQualifiedIdentifier/buildSelectTable/buildTableName/buildColumns so inherited DefaultSqlBuilder DQL/DML paths (exportTableData, insert, update) no longer concatenate raw identifiers.
  • The raw IColumnBuilder.buildDefaultColumn fallback is replaced with an escaped column name plus anchored type-shape validation (reject otherwise). Default-value/unit validators return trimmed values.
  • The DEFAULT-value function-call branch requires balanced single-quoted literals as arguments (bare/unbalanced quotes rejected), closing the unbalanced-quote gap in default validation.
  • Added XugudbSqlEscapesTest covering literal doubling, identifier doubling, malicious schema/table/column names via buildSelectTable/buildInsert, comment literals end-to-end, fallback name/type validation, validator trimming, and function-default quote balancing.

Affected surfaces

  • Frontend / Web
  • Backend / API / Storage
  • Database plugin / Driver
  • JCEF / Desktop packaging
  • CI / Build / Release
  • Documentation only

Verification

  • Command: mvn -B -pl chat2db-community-plugins/chat2db-community-xugudb -f chat2db-community-server/pom.xml -Dmaven.test.skip=false -DskipTests=false -Dsurefire.failIfNoSpecifiedTests=false -Dmaven.test.failure.ignore=false clean test
  • Result: Tests run: 19, Failures: 0, Errors: 0, Skipped: 0 (includes pre-existing module tests; log: F:/tmp/46/test-xugudb.log).
  • Manual verification: escaping is identity for names without special characters; a name containing " is emitted with doubled quotes inside a delimited identifier; invalid column types in the fallback path are rejected with IllegalArgumentException.

Risk and compatibility

  • Public API or stored data: N/A — only changes generated SQL for metadata/DDL/DML-builder paths.
  • Database or driver compatibility: quoted output matches XuguDB double-quote identifier rules; behavior for ordinary names is unchanged.
  • Network, privacy, or security: closes second-order SQL-injection paths in generated SQL.
  • Community / Local / Pro boundary: N/A.
  • Backward compatibility: names containing quote characters that previously produced broken/injectable SQL now produce correctly escaped SQL; invalid fallback column types are now rejected instead of emitted verbatim.
  • Known limitation: the DEFAULT-value pattern uses ^...$ anchors (a single trailing newline passes as inert whitespace; cosmetic, alignable to \A...\z later).

Reviewer map

  • Start here: XugudbSqlEscapes.java (new helper) and XugudbSqlEscapesTest.java.
  • Then: quoting call sites in XUGUDBMetaData / XUGUDBDBManager; the new builder overrides in XUGUDBSqlBuilder; the fallback validation in XUGUDBColumnTypeEnum.
  • Failure condition: a metadata/DDL/builder SQL string still interpolates an unescaped name or literal.
  • Rollback or disable path: revert the three commits on this branch.

Contributor declaration

  • I linked the Issue that defines this change.
  • I tested the affected behavior and reported the actual results above.
  • I did not include credentials, private data, or generated build output.
  • I disclosed substantial AI assistance below, or this PR contains no substantial AI-generated code.

AI assistance: The fix, verification, and PR description were produced with AI coding assistance.

…olumn fallback (OtterMind#1914)

- Override quoteIdentifier/quoteQualifiedIdentifier/buildSelectTable/buildTableName/
  buildColumns in XUGUDBSqlBuilder so inherited DefaultSqlBuilder DQL/DML paths
  (exportTableData, insert, update) no longer concatenate raw identifiers
- Replace raw IColumnBuilder.buildDefaultColumn fallback with escaped name +
  anchored type-shape validation (reject otherwise)
- Return trimmed values from default-value/unit validators
- Document raw-identifier contract on XugudbSqlEscapes.escapeIdentifier
- Add attack-string tests: malicious schema/table/column via buildSelectTable and
  buildInsert, comment literal end-to-end, fallback name/type, validator trimming
@HandSonic
HandSonic marked this pull request as draft July 26, 2026 10:30
@openai0229 openai0229 moved this from In Review to In Progress in Chat2DB Community Jul 26, 2026
… tests (OtterMind#1914)

- DEFAULT_VALUE_PATTERN function-call branch now requires balanced
  single-quoted literals as arguments ('([^']|'')*' allowed, bare quotes
  rejected), closing the unbalanced-quote gap in default-value validation
- Add tests: unbalancedQuoteInFunctionDefaultIsRejected,
  balancedQuotedArgsInFunctionDefaultAreAccepted
- Fix extra closing paren typo in the c3 case
@HandSonic
HandSonic marked this pull request as ready for review July 26, 2026 11:05
@openai0229 openai0229 moved this from In Progress to In Review in Chat2DB Community Jul 26, 2026
…intainer review (OtterMind#1914)

- new XugudbIdentifierProcessor (SPI ISQLIdentifierProcessor): quoteIdentifier
  with double-quote doubling, escapeString with single-quote doubling
- XUGUDBMetaData overrides getSQLIdentifierProcessor(); metadata call sites use it
- builder/manager/enums use XugudbIdentifierProcessor.INSTANCE
- non-escapable validation moved to XugudbSqlGuards (column defaults, length units)
- XugudbSqlEscapes removed; tests migrated (21 green)
…rough, conditional for SPI, always for DDL) (OtterMind#1914)

Found in re-review: processor was always-quote with null->"" garbage,
breaking SPI completion paths; no quoteIdentifierAlways existed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

3 participants