Summary
df.debug_connection() exposes the full PostgreSQL connection string used by the background worker, including the superuser role name, host, port, and database. This information should not be accessible to customers in a PaaS deployment.
Additionally, the background worker logs the full connection string to the PostgreSQL log on every startup, which is visible to customers who receive log copies.
Findings
1. df.debug_connection() grants too broad access
The function returns:
postgres://azuresu@127.0.0.1:5432/postgres (schema: duroxide)
This reveals:
- The worker role name (useful for targeted attacks)
- The host/port (confirming network topology)
- The target database name
- The duroxide schema name
Current state: debug_connection() is included in the func_sigs array inside df.grant_usage() (src/lib.rs), meaning every role granted basic pg_durable access can call it. It was never designed for customer use — it is a developer convenience for the extension authors to verify BGW configuration.
Customers already have safe alternatives for debugging:
df.target_database() — returns only the database name
df.version() — returns extension version and build timestamp
df.metrics() — returns system-wide execution statistics
df.instance_info(id) — returns instance details
Recommendation: Either:
- (a) Remove
debug_connection() entirely, or
- (b) Remove it from the
func_sigs array in df.grant_usage() so it is never granted to non-superuser roles (treat it like df.http() or the admin helpers)
2. Connection string logged unredacted to PG logs
In src/worker.rs line ~92:
log!(
"pg_durable: background worker connected to PostgreSQL at {} (schema: {})",
pg_conn_str,
DUROXIDE_SCHEMA
);
This emits the full connection string (including the worker role name) to the PostgreSQL log on every BGW start/restart. In our PaaS deployment, customers can obtain copies of PG logs.
Recommendation: Redact the role name from the log message. Log only the host:port/database, or mask the user component. The full connection string is useful for infrastructure owners, so consider a separate infrastructure-only log channel or redact only the sensitive portions.
Context
- Security review item: I-7 in
docs/security-review/security-review.md
- Affected files:
src/dsl.rs (function), src/worker.rs (log), src/lib.rs (grant_usage func_sigs)
- Severity: Medium
- Branch context: analysis performed on
pinodeca/http-mode-guc
Summary
df.debug_connection()exposes the full PostgreSQL connection string used by the background worker, including the superuser role name, host, port, and database. This information should not be accessible to customers in a PaaS deployment.Additionally, the background worker logs the full connection string to the PostgreSQL log on every startup, which is visible to customers who receive log copies.
Findings
1.
df.debug_connection()grants too broad accessThe function returns:
This reveals:
Current state:
debug_connection()is included in thefunc_sigsarray insidedf.grant_usage()(src/lib.rs), meaning every role granted basic pg_durable access can call it. It was never designed for customer use — it is a developer convenience for the extension authors to verify BGW configuration.Customers already have safe alternatives for debugging:
df.target_database()— returns only the database namedf.version()— returns extension version and build timestampdf.metrics()— returns system-wide execution statisticsdf.instance_info(id)— returns instance detailsRecommendation: Either:
debug_connection()entirely, orfunc_sigsarray indf.grant_usage()so it is never granted to non-superuser roles (treat it likedf.http()or the admin helpers)2. Connection string logged unredacted to PG logs
In
src/worker.rsline ~92:This emits the full connection string (including the worker role name) to the PostgreSQL log on every BGW start/restart. In our PaaS deployment, customers can obtain copies of PG logs.
Recommendation: Redact the role name from the log message. Log only the host:port/database, or mask the user component. The full connection string is useful for infrastructure owners, so consider a separate infrastructure-only log channel or redact only the sensitive portions.
Context
docs/security-review/security-review.mdsrc/dsl.rs(function),src/worker.rs(log),src/lib.rs(grant_usage func_sigs)pinodeca/http-mode-guc