fix(recovery): authenticate restored tenant RLS policy - #243
Draft
seonghobae wants to merge 17 commits into
Draft
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Contributor
Author
|
@cwl-noema-review |
seonghobae
changed the base branch from
main
to
fix/recovery-evidence-weakref-coverage-b84f0c9
August 19, 2026 00:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Security repair — authenticate restored tenant RLS policy
This Draft fails closed when isolated restore-catalog acceptance sees the lifecycle or checkpoint tenant RLS policy replaced by a same-name permissive or search-path-shadowed decoy. It originated from protected
main@b84f0c94154043a3473939c01bb6471de5a129aeand is an explicit child of dependency-root #233.Exact current stack — refreshed 2026-08-20
b84f0c94154043a3473939c01bb6471de5a129ae;fix/recovery-evidence-weakref-coverage-b84f0c9;5951b7a4d779903b8924abaef2a387cae50b7f54;5ca9ccc242f5feb77d674019ada7d2ae5d176f97;pg_llm_batch/postgres_restore_acceptance.py;tests/smoke_restore_catalog_index_semantics.py;tests/test_postgres_restore_acceptance_index_semantics.py; andtests/test_postgres_restore_catalog_evidence_serialization.py.Protected main, #233, canonical documentation, and adjacent recovery branches were not mutated.
Root cause and realistic RED
Protected main authenticated required tables, lifecycle index structure, and RLS enable/force flags but not the installed tenant policy object. Normalized
pg_get_expr(...)text alone is insufficient when a restored attacker-controlled schema precedespg_catalogonsearch_path: a user-definedpublic.=(text,text)that always returns true can bind into a newly created policy while deparsing to text visually identical totenant_scope = current_setting('pg_llm_batch.tenant_scope', true).Exact test-first head
1a999fcdb33986875e68be1f62ef50f9a4361739, CI32099148113, reproduced that live PostgreSQL exploit withsame-name decoy catalog object was accepted.A first remedy requiring positive
pg_dependrows for PostgreSQL built-ins was proven too strict by exact head744f87636abb57f41265c270fdaff573ed0586cf, CI32099559913: untouched packaged catalog was rejected because pinned system objects may have no ordinary dependency row.Corrected fail-closed remedy
The branch combines exact package policy name/command/roles/predicate checks, one-policy-only acceptance, schema-qualified catalog functions and
OPERATOR(pg_catalog.=)/OPERATOR(pg_catalog.<>)comparisons, and a negativepg_dependboundary that rejects normal dependencies on functions/operators other than the intended built-incurrent_setting(text,bool)and text equality identities. This permits dependency-row-free pinned built-ins while rejecting restored shadow objects.The live decoy creates an always-true
public.=(text,text), placespublicahead ofpg_catalog, recreates the package-named policy, proves rejection with the tenant-isolation category, removes the decoy, and proves the packaged catalog is accepted again.Serialization exact-type coverage repair
The post-policy serialization hardening on this branch added an exact-type guard for
PostgresRestoreCatalogEvidence, but the immediately preceding hosted run left that guard's subtype-rejection branch uncovered. The repository's exact 100% owned statement/branch contract therefore failed despite the RLS-authentication behavior being green.Current head
5ca9ccc242f5feb77d674019ada7d2ae5d176f97adds one narrow regression intests/test_postgres_restore_catalog_evidence_serialization.py: a subclass carrying otherwise-valid evidence must fail through the fixedPostgresRestoreAcceptanceErrorboundary with no chained diagnostic. No production source changed in this follow-up commit.Pre-follow-up evidence
The earlier stacked source head had Python 3.10/3.12/3.14 unit success, PostgreSQL/container success including the live decoy smoke, compile/Ruff/public-docstring success, and all changed production source exercised except the newly introduced exact-type branch. Security Scan, SAST Semgrep, and Release Acceptance were terminal-success on the corresponding exact predecessor. That evidence establishes causality only and does not transfer to the current head.
Current exact-head validation
Fresh formal reviews and inline review threads are empty; absence of review is not approval. Exact current head
5ca9ccc242f5feb77d674019ada7d2ae5d176f97now has:32338167073: completed / success;32338167046: completed / success;CI and Release Acceptance therefore prove the exact current checkout, including the branch's Python matrix/coverage/package and release-acceptance work, but absent Security Scan / SAST evidence remains non-passing. Keep this PR Draft and unchanged unless a branch-owned defect or material dependency state change appears.
Integration boundary — refreshed 2026-08-30
#233 is the exact predecessor and must integrate first. Its former read-only central coverage/review failure is historical RCA rather than the current evidence-capability boundary. Unchanged #233 now has fresh exact-contributor-head CI, Release Acceptance, Trivy Security Scan, Semgrep SAST, and bounded Strix evidence under protected central semantics. None of that evidence transfers to this child.
#233 remains non-passing because its active same-head OpenCode formal state is still
CHANGES_REQUESTED, that disposition has not been superseded by a genuinely fresh qualifying semantic review, and no qualifying approval exists under live governance. Mutable control-plane/reviewer/provider truth belongs in pg-owned #244; central.githubremains read-only. Do not copy central logic into this repository, churn #233 or this child merely to manufacture an event, dismiss substantive review state, or transfer predecessor evidence.After #233 integrates, retarget/reconcile this PR to then-current protected main, prove the reconciled diff remains bounded to this recovery-authentication/serialization-test slice, and reacquire every exact-final-head/current-base Python including 3.14, exact 100% owned production statement/branch coverage, public docstrings, security/SAST, package/SBOM/provenance/release, formal-review, unresolved-thread, and live-governance gate. No predecessor, queued, absent, infrastructure-failed, status-only, author-only, or other-branch evidence transfers.
No schema/policy mutation is performed by production code. No RPO/RTO, PITR, DR, CSAP, SOC 2, or certification claim follows from this bounded acceptance primitive.
Refs #204, #233, #244, #279.