Skip to content

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

Open
HandSonic wants to merge 4 commits into
OtterMind:mainfrom
HandSonic:fix/sqli2-postgresql
Open

fix(postgresql): escape SQL identifiers and literals in metadata/DDL paths (#1914)#2194
HandSonic wants to merge 4 commits into
OtterMind:mainfrom
HandSonic:fix/sqli2-postgresql

Conversation

@HandSonic

Copy link
Copy Markdown
Contributor

Part of the SQL-injection hardening tracked in #1914. Prior art: #2052 (Oracle), #2053 (SQL Server), and the wave-1 batch (#2172-#2177).

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.

What changed (14 sites)

Promotes the two private quoting statics into a module-level PostgreSqlEscapes and applies them across metadata/DDL paths (MetaData, DBManager DROP DATABASE, SqlBuilder view/schema paths).

Verification

mvn -B -pl chat2db-community-plugins/chat2db-community-postgresql -f chat2db-community-server/pom.xml -Dmaven.test.skip=false -DskipTests=false -Dsurefire.includes=**/*Test.java -Dsurefire.failIfNoSpecifiedTests=false -Dmaven.test.failure.ignore=false test

Result: Tests run: 38, Failures: 0, Errors: 0, Skipped: 0.

This branch also passed a two-lens adversarial review (escape-correctness/coverage + regression/test-efficacy); all blocking findings were fixed and re-tested before submission.

…r per maintainer review (OtterMind#1914)

- PostgreSQLIdentifierProcessor (SPI ISQLIdentifierProcessor): quoteIdentifier
  always double-quotes with embedded-quote doubling, escapeString with
  single-quote doubling; INSTANCE shared by call sites
- PostgreSQLMetaData.getSQLIdentifierProcessor() returns the processor;
  metadata call sites use it (POSTGRE_SQL_IDENTIFIER_PROCESSOR removed)
- builders/managers/enums/templates use PostgreSQLIdentifierProcessor.INSTANCE
- non-escapable validation moved to PostgreSqlGuards (pg names, default
  expressions, bit/hex literals, enum options)
- PostgreSqlEscapes removed; tests migrated (38 green)
…-quote for DDL paths (OtterMind#1914)

- quoteIdentifier(String) is conditional again: null/blank passthrough, valid
  non-keyword identifiers returned unquoted, everything else wrapped with
  embedded-quote doubling; versioned overload delegates to it
- quoteIdentifierIgnoreCase is the always-quote SPI variant (preserves case)
- new quoteIdentifierAlways(String) for DDL-generation call sites migrated
  from PostgreSqlEscapes.quoteIdentifier (DBManager, SqlBuilder DDL paths,
  column/index type enums, MetaData format/getMetaDataName)
- buildTableName/buildColumns keep conditional processor quoting
- tests cover conditional, always-quote, ignoreCase and null passthrough
  (40 green)
…oteIdentifier (OtterMind#1914)

PostgreSQL folds unquoted identifiers to lowercase, so the conditional
quoteIdentifier must quote names containing uppercase (as Oracle/DM do).
Found in adversarial confirmation.
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.

2 participants