Skip to content

libsql-server: enforce namespace authorization on gRPC replication RPCs - #29

Closed
bartzon wants to merge 1 commit into
libsql-rs-v0.9.30-releasefrom
replication-namespace-authz
Closed

libsql-server: enforce namespace authorization on gRPC replication RPCs#29
bartzon wants to merge 1 commit into
libsql-rs-v0.9.30-releasefrom
replication-namespace-authz

Conversation

@bartzon

@bartzon bartzon commented Sep 7, 2026

Copy link
Copy Markdown

Problem

The gRPC replication path in libsql-server validates a JWT's signature but never checks its ns claim against the namespace being served:

  • rpc/replication/auth.rs calls auth.authenticate(context)? and discards the returned Authenticated.
  • The four replication RPCs (Hello/LogEntries/BatchLogEntries/Snapshot) in replication_log.rs then call namespaces.with(...) directly — nothing compares p.ro.ns against the namespace being replicated.

Empirically confirmed on staging: with a token scoped to namespace A, an embedded-replica client (Builder::new_remote_replica + sync() — the same path a POS device uses) synced namespace B's entire database. HTTP paths are unaffected (they go through with_authenticatedis_namespace_authorized).

Fix

In rpc/replication/auth.rs, keep the Authenticated and call is_namespace_authorized(&namespace), returning permission_denied on mismatch. One change covers all four RPCs.

is_namespace_authorized on Legacy{ namespace: None } returns true, so no-namespace/legacy tokens (e.g. the CloudSync streamer) still replicate every namespace — no regression for server-side callers.

Test

Adds replicate_cross_namespace_denied (tests/embedded_replica/mod.rs): ns1-scoped token replicates ns1 (control), is denied on ns2 (the bug), and a both-namespaces token replicates both (control). Upstream's replicate_auth only asserts token-present vs token-absent; this is the missing negative cross-namespace test.

Notes

  • cargo check -p libsql-server and --tests pass clean. The test run needs Linux/CI (libsql-server tests don't link on macOS/arm64).
  • Base branch libsql-rs-v0.9.30-release is the libsql-rs-v0.9.30+connection-initialization-patch tag materialized as a branch (PRs can't target tags).

The replication path validated the JWT signature but discarded the
returned Authenticated, so any valid token could replicate any
namespace regardless of its ns claim. Check is_namespace_authorized
against the served namespace and add a negative cross-namespace test.
@bartzon bartzon self-assigned this Sep 7, 2026
@bartzon
bartzon requested a review from a team September 7, 2026 13:49
@bartzon

bartzon commented Sep 7, 2026

Copy link
Copy Markdown
Author

Closing — opened in error; will be resubmitted through the proper channel.

@bartzon bartzon closed this Sep 7, 2026
@bartzon
bartzon deleted the replication-namespace-authz branch September 7, 2026 13:59
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.

1 participant