Skip to content

fix: address security review findings for 1.0 GA#270

Merged
tjgreen42 merged 10 commits intomainfrom
security-hardening
Mar 13, 2026
Merged

fix: address security review findings for 1.0 GA#270
tjgreen42 merged 10 commits intomainfrom
security-hardening

Conversation

@tjgreen42
Copy link
Copy Markdown
Collaborator

@tjgreen42 tjgreen42 commented Mar 9, 2026

Summary

Addresses findings 1-5 from the pre-GA security code review:

  • (High) Missing authorization on spill/merge: Add superuser() checks to tp_spill_memtable and tp_force_merge so unprivileged users cannot trigger segment writes or full compaction
  • (High) OOB read via crafted bm25vector: Add cross-field validation in tpvector_recv ensuring total_size is consistent with index_name_len and entry_count
  • (High) No REVOKE on public functions: Add REVOKE EXECUTE FROM PUBLIC on all admin/debug functions in install SQL and all upgrade migration scripts
  • (Medium) Assert-only decompression bounds checks: Replace Assert() with runtime ereport(ERROR) for count, doc_id_bits, and freq_bits in tp_decompress_block — prevents stack buffer overflows from corrupted segments in release builds
  • (Medium) Resource GUCs are PGC_USERSET: Change bulk_load_threshold, memtable_spill_threshold, and segments_per_level to PGC_SUSET

Lower-severity findings (6-11: logging GUCs, debug file paths, tranche IDs, prerelease warning, relocatable flag, test identifier quoting) are not addressed in this PR.

Testing

  • Security test expanded to cover spill/merge authorization, REVOKE privilege checks, and GUC permission enforcement
  • All 50 regression tests pass

Addresses findings 1-5 from the pre-GA security code review:

1. (High) Add superuser() checks to tp_spill_memtable and tp_force_merge
   so unprivileged users cannot trigger segment writes or compaction.

2. (High) Add cross-field validation in tpvector_recv to ensure
   total_size is consistent with index_name_len and entry_count,
   preventing out-of-bounds reads from crafted binary protocol input.

3. (High) Add REVOKE EXECUTE FROM PUBLIC on all administrative and
   debug functions (bm25_spill_index, bm25_force_merge, bm25_dump_index,
   bm25_summarize_index, bm25_debug_pageviz) in the install SQL and
   all upgrade migration scripts.

4. (Medium) Replace Assert-only bounds checks in tp_decompress_block
   with runtime ereport(ERROR) checks for count, doc_id_bits, and
   freq_bits. These protect against stack buffer overflows from
   corrupted on-disk segment data in release builds.

5. (Medium) Change bulk_load_threshold, memtable_spill_threshold, and
   segments_per_level GUCs from PGC_USERSET to PGC_SUSET so
   unprivileged users cannot manipulate resource-control parameters.

Security test updated to cover all new restrictions.
Replace superuser() with object_ownercheck() for bm25_spill_index and
bm25_force_merge. These are operational functions that the index owner
(or any superuser) should be able to call — not just superusers.

Remove REVOKE FROM PUBLIC on spill/merge since any user who owns the
index should be able to call them. REVOKE remains on debug functions
(dump, summarize, pageviz) which are superuser-only.
bm25_debug_pageviz was added in the 0.5.0 base install but not in
any upgrade script, so it doesn't exist when upgrading from pre-0.5.0
versions (e.g., 0.4.2 → 0.5.0 → 1.0.0-dev). Use a conditional
REVOKE to avoid failing on the missing function.
pgspot requires qualified operators in extension SQL.
@tjgreen42 tjgreen42 marked this pull request as ready for review March 11, 2026 19:11
Address code review feedback on the cross-field validation in
tpvector_recv: use Size instead of int for min_payload to prevent
integer overflow with large entry_count, and add per-entry validation
loop to ensure each entry's lexeme data stays within the buffer.

Also harden tpvector_out to check lexeme data bounds before memcpy,
and fix security test to use fresh extension install so REVOKE
statements are applied.
@tjgreen42 tjgreen42 force-pushed the security-hardening branch from 2603ba2 to a80a3f0 Compare March 11, 2026 22:18
- (6) Change log_scores and log_bmw_stats GUCs from PGC_USERSET to
  PGC_SUSET to prevent info disclosure in connection-pooled environments
- (7) Gate file-writing debug functions (bm25_dump_index two-arg and
  bm25_debug_pageviz) behind #ifdef DEBUG_DUMP_INDEX; remove from GA
  install SQL and add DROP in upgrade scripts
- (8) Document fixed LWLock tranche IDs 1001-1008 in README
- (10) Set relocatable = false to prevent schema ambiguity with planner
  hooks
- (11) Fix SQL injection in test/sql/validation.sql: %s -> %L for
  regconfig arguments in format() calls
@tjgreen42 tjgreen42 marked this pull request as draft March 12, 2026 18:03
@tjgreen42 tjgreen42 marked this pull request as ready for review March 12, 2026 18:03
@tjgreen42 tjgreen42 requested a review from mostafa March 12, 2026 18:06
Copy link
Copy Markdown
Member

@mostafa mostafa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing these issues. LGTM! 🚀

@tjgreen42 tjgreen42 merged commit d67a7bd into main Mar 13, 2026
33 checks passed
@tjgreen42 tjgreen42 deleted the security-hardening branch March 13, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants