Skip to content

fix(db2): escape SQL identifiers and literals in metadata/DDL paths (#1914) - #2173

Merged
openai0229 merged 7 commits into
OtterMind:mainfrom
HandSonic:fix/sqli-db2
Jul 29, 2026
Merged

fix(db2): escape SQL identifiers and literals in metadata/DDL paths (#1914)#2173
openai0229 merged 7 commits into
OtterMind:mainfrom
HandSonic:fix/sqli-db2

Conversation

@HandSonic

@HandSonic HandSonic commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Related issue

Closes #1914

Summary

Escapes DB2 identifiers and SQL string literals throughout metadata, export, and DDL-generation paths.

  • Adds a DB2 identifier processor with conditional quoting, DB2 case-folding and reserved-word handling, unconditional quoting, embedded-delimiter escaping, and exact quote/remove round trips.
  • Escapes object names and comments in table, schema, column, index, copy, drop, truncate, metadata, and export SQL.
  • Preserves legal DB2 defaults, including string and numeric literals, temporal values, special registers, supported no-argument functions, and sequence expressions, while rejecting structural breakout payloads.
  • Validates non-escapable type, length-unit, sort-direction, and db2look option positions.
  • Binds the complete db2look option string as a JDBC parameter instead of interpolating it into the stored-procedure call.

Affected surfaces

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

Verification

  • Commands and results: mvn -B -f chat2db-community-server/pom.xml -pl chat2db-community-plugins/chat2db-community-db2 -am -Dmaven.test.skip=false -DskipTests=false clean test -> BUILD SUCCESS; DB2 tests 29/29 passed, with all upstream reactor tests passing.
  • Manual verification: Reviewed every changed interpolation context and exercised generated SQL with embedded single quotes, double quotes, comments, delimiters, trailing newlines, qualified names, legal DB2 defaults, and db2look option payloads. No live DB2 server integration was available locally.
  • UI evidence: N/A

Risk and compatibility

  • Public API or stored data: No public API or stored-data format change. The DB2 plugin now implements the shared identifier processor contract.
  • Database or driver compatibility: Scoped to DB2 LUW SQL generation. Legal common defaults are preserved; unsupported free-form default expressions continue to fail closed. The db2look call now uses standard JDBC input/output binding.
  • Network, privacy, or security: No network or privacy change. Dynamic DB2 identifiers, literals, and db2look inputs no longer cross SQL structural boundaries unescaped.
  • Community / Local / Pro boundary: Community DB2 plugin only.
  • Backward compatibility: Safe uppercase ordinary identifiers remain unquoted. Lowercase, mixed-case, reserved, and delimiter-bearing names are quoted so DB2 does not fold or reinterpret them.

Reviewer map

  • Start here: Db2IdentifierProcessor, Db2SqlGuards, and Db2IdentifierProcessorTest.
  • Failure condition: A valid production DB2 default is outside the explicit accepted forms, or the target DB2 driver rejects the two-parameter callable statement used by DB2LK_GENERATE_DDL.
  • Rollback or disable path: Revert this PR; there is no runtime feature flag.

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: Codex was used for maintainer review, implementation corrections, and test updates.

@HandSonic
HandSonic requested a review from openai0229 as a code owner July 26, 2026 09:48
@openai0229 openai0229 moved this to In Review in Chat2DB Community Jul 26, 2026
@HandSonic
HandSonic marked this pull request as draft July 26, 2026 09:56
@HandSonic

Copy link
Copy Markdown
Contributor Author

Converting to draft: final adversarial review pass is still in progress for this branch. Will mark ready for review once it completes. (process note: PR was opened prematurely by automation)

@openai0229 openai0229 moved this from In Review to In Progress in Chat2DB Community Jul 26, 2026
@HandSonic
HandSonic marked this pull request as ready for review July 26, 2026 10:28
@openai0229 openai0229 moved this from In Progress to In Review in Chat2DB Community Jul 26, 2026
@HandSonic
HandSonic marked this pull request as draft July 26, 2026 10:57
@openai0229 openai0229 moved this from In Review to In Progress in Chat2DB Community Jul 26, 2026
@HandSonic
HandSonic marked this pull request as ready for review July 26, 2026 11:33
@openai0229 openai0229 moved this from In Progress to In Review in Chat2DB Community Jul 26, 2026
HandSonic and others added 7 commits July 29, 2026 13:47
…aths (OtterMind#1914)

- buildCreateColumnSql fallback: validate columnType against a strict
  type-shape whitelist and escape the column name as a delimited
  identifier instead of delegating to the raw SPI buildDefaultColumn
- tableDDL: reject schema/table names containing double quotes, which
  would otherwise break out of the db2look -td/-t option string
- add regression tests for both paths plus SET SCHEMA, dropTable and
  copyTable escaping composition
…t validation (OtterMind#1914)

- DB2SqlBuilder: override buildDropTable/buildTruncateTable so qualified
  table names are quoted via Db2SqlEscapes instead of the SPI identity
- DB2DBManager: override truncateTable with the same quoting
- DB2ColumnTypeEnum.getByType: strip size suffix so VARCHAR(10) resolves
  to the enum and reaches the validated fallback instead of being skipped
- DB2ColumnTypeEnum: drop parens/comma from DEFAULT_VALUE_PATTERN to block
  column-definition breakout via crafted default values
- add regression tests for all four paths
…ayloads (OtterMind#1914)

- DEFAULT_VALUE_PATTERN: drop single-quote from the allowed class so
  crafted defaults cannot toggle string-literal context inside the
  enclosing CREATE/ALTER statement
- anchor DEFAULT_VALUE_PATTERN, UNIT_PATTERN and
  FALLBACK_COLUMN_TYPE_PATTERN with \A/\z instead of ^/$ so a trailing
  newline can no longer smuggle input past validation
- validateAscOrDesc needs no anchor change: it uses exact string
  equality, which is already absolute
- add rejection tests for quote/comma/paren breakout defaults,
  trailing-newline bypasses, and GET_DDL_TOKEN option-string quoting
…er review (OtterMind#1914)

- new Db2IdentifierProcessor (SPI ISQLIdentifierProcessor): quoteIdentifier
  with double-quote doubling, escapeString with single-quote doubling
- DB2MetaData overrides getSQLIdentifierProcessor(); metadata call sites use it
- builders/managers/enums use Db2IdentifierProcessor.INSTANCE
- non-escapable validation moved to Db2SqlGuards (default values, length
  units, fallback column types, index sort directions)
- Db2SqlEscapes removed; tests migrated (23 green)

@openai0229 openai0229 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer review complete. Identifier round-trip, DB2 case folding, legal default expressions, and db2look parameter binding were corrected; clean DB2 reactor tests pass.

@openai0229
openai0229 merged commit d1f377b into OtterMind:main Jul 29, 2026
19 checks passed
@openai0229 openai0229 moved this from In Review to Done in Chat2DB Community Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Security: 34 SQL Injection Vulnerabilities in Database Plugins

2 participants