Summary
borp's dialect identifier quoting helpers wrap identifiers in dialect quote
characters but do not escape embedded quote characters. Mapper metadata such as
table, column, schema, or index names can therefore break out of the quoted
identifier and change generated SQL.
Affected area
Tested on main at c0288adf3b533244dd2bf2fca08ca4418b25d281.
Affected helpers:
SqliteDialect.QuoteField
PostgresDialect.QuoteField
MySQLDialect.QuoteField
QuotedTableForQuery callers
- generated DML and index DDL paths
Reproduction
With SQLite, register a mapped table name containing an embedded quote:
victim" SET admin = 1 WHERE ? <> ? --
Before escaping, generated update SQL can become:
update "victim" SET admin = 1 WHERE ? <> ? -- " set "ID"=?, "Value"=? where "ID"=?;
A focused regression shows this changes victim.admin from 0 to 1 through
the mapped table name.
Expected behavior
Identifier metadata should either be rejected or escaped so it cannot change
generated SQL structure.
Actual behavior
QuoteField concatenates the opening quote, raw identifier, and closing quote.
Embedded dialect quote characters terminate the quoted identifier.
Impact
This is a SQL injection surface for downstream consumers that let external input
influence mapper metadata. I did not find a Boulder path where external input
controls borp mapper metadata; the affected surface is borp library consumers
that do expose that kind of mapping.
Suggested fix
Escape the dialect-specific identifier quote character:
- SQLite/PostgreSQL: double embedded
" characters.
- MySQL: double embedded backticks.
Add regression coverage for DML generated from table metadata and DDL generated
from index, schema, and table metadata.
Summary
borp's dialect identifier quoting helpers wrap identifiers in dialect quote
characters but do not escape embedded quote characters. Mapper metadata such as
table, column, schema, or index names can therefore break out of the quoted
identifier and change generated SQL.
Affected area
Tested on
mainatc0288adf3b533244dd2bf2fca08ca4418b25d281.Affected helpers:
SqliteDialect.QuoteFieldPostgresDialect.QuoteFieldMySQLDialect.QuoteFieldQuotedTableForQuerycallersReproduction
With SQLite, register a mapped table name containing an embedded quote:
victim" SET admin = 1 WHERE ? <> ? --Before escaping, generated update SQL can become:
update "victim" SET admin = 1 WHERE ? <> ? -- " set "ID"=?, "Value"=? where "ID"=?;A focused regression shows this changes
victim.adminfrom0to1throughthe mapped table name.
Expected behavior
Identifier metadata should either be rejected or escaped so it cannot change
generated SQL structure.
Actual behavior
QuoteFieldconcatenates the opening quote, raw identifier, and closing quote.Embedded dialect quote characters terminate the quoted identifier.
Impact
This is a SQL injection surface for downstream consumers that let external input
influence mapper metadata. I did not find a Boulder path where external input
controls borp mapper metadata; the affected surface is borp library consumers
that do expose that kind of mapping.
Suggested fix
Escape the dialect-specific identifier quote character:
"characters.Add regression coverage for DML generated from table metadata and DDL generated
from index, schema, and table metadata.