Skip to content

security(dbml): define identifier-to-DDL trust boundary without deny-list drift #747

Description

@seonghobae

Buyer and security problem

DBML relation and column identifiers eventually participate in generated PostgreSQL DDL. Pull request #719 bundled a broad deny-list validator with an unrelated column-position optimization, frontend dependency drift, and other changes. That validator should not be merged incidentally: PostgreSQL permits quoted identifiers containing spaces and many punctuation characters, while a generic deny-list can both reject legitimate schemas and still miss dialect-specific construction errors.

Required bounded slice

  • trace every DBML identifier from parser input through snapshot storage to every SQL/DDL rendering sink;
  • keep parsing, canonical representation, and PostgreSQL rendering as separate contracts;
  • reject NUL, malformed quoting, unterminated identifiers, excessive UTF-8 byte length, ambiguous path segmentation, and resource-exhaustion inputs fail-closed;
  • preserve valid PostgreSQL quoted identifiers, including embedded double quotes represented by doubled quotes;
  • never concatenate an unvalidated identifier directly into executable SQL;
  • use one dialect-owned identifier quoting/rendering function at every DDL sink, or redesign the sink around a structured AST;
  • keep values parameterized wherever bind parameters are legal;
  • add realistic tests for ordinary, Unicode, reserved-word, whitespace, embedded-quote, semicolon, comment-marker, NUL, overlength, and multi-segment identifiers;
  • prove generated DDL parses as one intended statement and cannot append a second statement or comment out required syntax;
  • add fuzz/property tests for parse→canonicalize→render round trips;
  • maintain 100% production statement/branch coverage and complete public docstrings;
  • update ARCHITECTURE.md, AGENTS.md or the authoritative security/doctoring record, and CHANGELOG.md.

Acceptance boundary

The performance-only O(N) column-position change proceeds in #746. This issue is a separate security contract and must not reintroduce #719's unrelated frontend lock drift or use a generic character deny-list as the sole defense.

Standards and primary documentation — APA 7th

Open Worldwide Application Security Project. (2026). SQL injection prevention cheat sheet. OWASP Cheat Sheet Series. https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html

PostgreSQL Global Development Group. (2026). PostgreSQL 18 documentation: Lexical structure. https://www.postgresql.org/docs/18/sql-syntax-lexical.html

These sources are engineering guidance; no formal compliance claim is made.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions