Skip to content

fix(persistence): fail closed on committed DO blocks that hide execution-context mutations #582

Description

@seonghobae

Finding

#576#581 fold committed session_replication_role mutations through direct SET, PostgreSQL's set_config(...), and writable pg_settings.setting. The shared lexical authority deliberately makes dollar-quoted bodies opaque. PostgreSQL DO, however, executes its code body immediately as a transient anonymous function. A committed migration can therefore hide an execution-context mutation inside a DO body:

DO $$
BEGIN
  PERFORM set_config('session_replication_role', 'replica', false);
END
$$;

After lexical normalization the dollar body is intentionally masked, so the current execution-context fold sees only a DO statement and cannot prove that ordinary append-only/retention triggers remained enabled. With is_local=false, the set_config value is session-scoped; even transaction-local mutations can permit protected DML to commit while ordinary triggers are suppressed.

PostgreSQL 18 authority:

Contract

At exported validate_migration_catalog():

  • a committed top-level DO block must fail closed with MissingAppRuntimeRole until TEPP owns executable procedural-body semantics;
  • DO LANGUAGE plpgsql $$...$$ and DO $$...$$ LANGUAGE plpgsql are the same execution-risk boundary;
  • a DO block inside an explicit transaction that rolls back remains non-durable through fix(persistence): exclude rolled-back membership mutations from RLS safety evidence #560 committed-state projection and must not poison final validation;
  • dollar-quoted text used as data (SELECT $$DO ...$$) and marker text inside comments/literals must remain inert;
  • CREATE FUNCTION/PROCEDURE ... AS $$...$$ must not be rejected merely because its body is opaque: definition is not immediate execution;
  • do not parse PL/pgSQL locally or introduce a second raw-SQL lexer. Reuse the shared lexical normalization: after the body is masked, a committed statement whose first structural token is exactly DO is unprovable execution context and therefore fails closed.

This is a bounded safety repair, not the architectural endpoint. The long-term execution-context aggregate should model immediately executed procedural SQL, nested dynamic SQL, configuration mutation, protected-DML ordering, privileges, and transaction outcome explicitly.

Keep open until post-#538 non-force-restack exact-head hosted Rust/Live PostgreSQL, current-topology rustdoc/coverage/security, 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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions