Skip to content

fix(recovery): authenticate restored tenant RLS policy - #243

Draft
seonghobae wants to merge 17 commits into
fix/recovery-evidence-weakref-coverage-b84f0c9from
fix/restore-catalog-policy-authentication-b84f0c9
Draft

fix(recovery): authenticate restored tenant RLS policy#243
seonghobae wants to merge 17 commits into
fix/recovery-evidence-weakref-coverage-b84f0c9from
fix/restore-catalog-policy-authentication-b84f0c9

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

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@b84f0c94154043a3473939c01bb6471de5a129ae and is an explicit child of dependency-root #233.

Exact current stack — refreshed 2026-08-20

  • protected main remains exact b84f0c94154043a3473939c01bb6471de5a129ae;
  • current base branch: fix/recovery-evidence-weakref-coverage-b84f0c9;
  • exact base SHA: 5951b7a4d779903b8924abaef2a387cae50b7f54;
  • exact current head SHA: 5ca9ccc242f5feb77d674019ada7d2ae5d176f97;
  • Draft and mechanically mergeable;
  • relative PR diff is exactly:
    • pg_llm_batch/postgres_restore_acceptance.py;
    • tests/smoke_restore_catalog_index_semantics.py;
    • tests/test_postgres_restore_acceptance_index_semantics.py; and
    • tests/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 precedes pg_catalog on search_path: a user-defined public.=(text,text) that always returns true can bind into a newly created policy while deparsing to text visually identical to tenant_scope = current_setting('pg_llm_batch.tenant_scope', true).

Exact test-first head 1a999fcdb33986875e68be1f62ef50f9a4361739, CI 32099148113, reproduced that live PostgreSQL exploit with same-name decoy catalog object was accepted.

A first remedy requiring positive pg_depend rows for PostgreSQL built-ins was proven too strict by exact head 744f87636abb57f41265c270fdaff573ed0586cf, CI 32099559913: 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 negative pg_depend boundary that rejects normal dependencies on functions/operators other than the intended built-in current_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), places public ahead of pg_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 5ca9ccc242f5feb77d674019ada7d2ae5d176f97 adds one narrow regression in tests/test_postgres_restore_catalog_evidence_serialization.py: a subclass carrying otherwise-valid evidence must fail through the fixed PostgresRestoreAcceptanceError boundary 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 5ca9ccc242f5feb77d674019ada7d2ae5d176f97 now has:

  • CI 32338167073: completed / success;
  • Release Acceptance 32338167046: completed / success;
  • exact-head Security Scan / SAST Semgrep: not materialized in the commit-scoped pull-request workflow inventory.

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 .github remains 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.

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

@cwl-noema-review

@seonghobae
seonghobae changed the base branch from main to fix/recovery-evidence-weakref-coverage-b84f0c9 August 19, 2026 00:17
@opencode-agent opencode-agent Bot added area: auth Authentication, authorization, identity, or tenant isolation area: operations Operability, observability, readiness, SLO, backup, or retention priority: medium Normal-priority or P2 work scope: research Research, statistical validation, or scientific evidence status: draft Draft pull request type: bug Defect or incorrect behavior labels Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: auth Authentication, authorization, identity, or tenant isolation area: operations Operability, observability, readiness, SLO, backup, or retention priority: medium Normal-priority or P2 work scope: research Research, statistical validation, or scientific evidence status: draft Draft pull request type: bug Defect or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant