Skip to content

fix(persistence): fail closed on Unicode-escaped set_config builtin identity #587

Description

@seonghobae

Finding

#585/#586 bound PostgreSQL Unicode-escaped identifier spellings for writable pg_settings and direct generic SET, but the set_config(...) execution-context path still discovers the builtin by searching normalized text for the literal substring set_config and then classifying only ordinary unqualified or pg_catalog. identity. The shared lexer does not yet decode PostgreSQL U&"..." identifiers to their final identifier identity.

PostgreSQL 18 accepts Unicode-escaped quoted identifiers and decodes code-point escapes before ordinary identifier semantics. Therefore canonical builtin spellings such as:

SELECT U&"set_\0063onfig"('session_replication_role', 'replica', false);

and canonical schema qualification such as:

SELECT U&"pg_\0063atalog".set_config('session_replication_role', 'replica', false);

resolve to PostgreSQL's set_config builtin path but can avoid the current literal-name/builtin-identity matcher after lexical projection. set_config is PostgreSQL's function equivalent of SET, and session_replication_role=replica suppresses ordinary/default triggers and rules. This can therefore bypass append-only/retention execution-context enforcement while final catalog definitions still look safe.

Primary PostgreSQL 18 authority:

Required contract

At exported validate_migration_catalog():

  • committed U&"set_\0063onfig"('session_replication_role','replica',false) must fail the runtime-role contract;
  • canonical Unicode-escaped pg_catalog qualification must cross the same boundary;
  • explicit UESCAPE spellings equivalent to set_config / pg_catalog must not bypass detection;
  • direct safe origin / local values remain accepted once builtin identity is established;
  • unrelated Unicode-escaped function/schema identities remain unrelated when the shared projection proves they are unrelated;
  • rollback remains non-durable through the existing committed-state projection;
  • comments, ordinary strings, and dollar-quoted bodies remain inert;
  • do not add a second raw-SQL lexer. The architectural endpoint remains shared PostgreSQL Unicode identifier decoding plus the first-class execution-context aggregate.

Keep open until post-#538 non-force-restack exact-head hosted Rust/Live PostgreSQL, current-topology rustdoc/coverage/security, resolved valid findings, and qualifying independent approval exist. Draft-skipped execution is not GREEN.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions