Skip to content

Redact the DB password (ODBC PWD and libpq pqopt password) in debug logs - #206

Open
davecramer wants to merge 2 commits into
mainfrom
fix-password-in-debug-log
Open

Redact the DB password (ODBC PWD and libpq pqopt password) in debug logs#206
davecramer wants to merge 2 commits into
mainfrom
fix-password-in-debug-log

Conversation

@davecramer

@davecramer davecramer commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Problem

hide_password() exists to mask the password in a connection string before it is written to the log, so that MyLog/CommLog output can be shared for debugging without leaking the database credentials.

It was compiled out by an unconditional #define FORCE_PASSWORD_DISPLAY (present since 2013). With MyLog (Debug) enabled, the driver therefore logged the full connection string -- including the password in cleartext.

Two forms of password leaked:

  1. The ODBC PWD= attribute (connStrIn, szConnStrOut, our_connect_string log sites in drvconn.c).
  2. A libpq password= embedded in a pqopt={...} value -- via szConnStrOut and via the per-attribute logging in copyConnAttributes (dlg_specific.c). hide_password() did not know about the libpq password= keyword.

Reproduced against PostgreSQL 18 for both forms, including a single-quoted pqopt={... password='my secret'}.

Fix

  • Remove the FORCE_PASSWORD_DISPLAY define so the existing redaction branches are actually used.
  • Move hide_password() to misc.c so it can be shared, and teach it to mask both keywords, case-insensitively:
    • PWD= -- ODBC attribute; value runs to the next ;.
    • password= -- libpq keyword (e.g. inside pqopt); value is whitespace-delimited or single-quoted (backslash escapes honored) and ends at the closing brace.
  • Redact the pqopt value where copyConnAttributes logs it, and skip the generic raw logging for that key. Non-secret pqopt fields (host, sslmode, application_name, ...) stay visible for debugging.
  • Fix the pointer-sign and format (ssize_t) warnings in the szConnStrOut redaction branch that were previously never compiled.

After the fix the same connections log PWD=xxxx, password=xxxx, and password='xxxx' (quoted) -- verified with PWD=/pwd=/Pwd= and unquoted/quoted pqopt passwords; no cleartext remains.

Scope / severity

Logging is off by default (mylog_on = 0; the MYLOG macro is a no-op and no log file is created unless debug logging is explicitly enabled), so this only affected users who turned on debug tracing, and additionally required access to the resulting log file. No default-on exposure, no remote vector. Low-severity hardening (CWE-532); no CVE.

Reported-by: @Alpop12

hide_password() masks the PWD value in a connection string before it is
logged, so MyLog/CommLog output can be shared for debugging without
leaking the database credentials.  It was compiled out by an
unconditional '#define FORCE_PASSWORD_DISPLAY' (present since 2013), so
with MyLog enabled the driver logged the full connection string --
including PWD=... in cleartext -- at the connStrIn, szConnStrOut and
our_connect_string log sites.

Remove the FORCE_PASSWORD_DISPLAY define so the existing redaction is
actually used, and make the PWD match case-insensitive so an
application-supplied 'Pwd='/'pwd=' is masked as well as the driver's own
'PWD='.  Also fixes the pointer-sign and format warnings in the
szConnStrOut redaction branch that were previously never compiled.

Logging is off by default, so this only affected users who explicitly
enabled debug logging; no default-on exposure.

Reported-by: Alpop12
hide_password() only masked the ODBC 'PWD=' attribute, so a password
embedded in a libpq pqopt value (pqopt={... password=secret}) still
leaked into MyLog via szConnStrOut (drvconn.c) and via the per-attribute
logging in copyConnAttributes (dlg_specific.c).

Move hide_password() to misc.c so it can be shared, and teach it to mask
the libpq 'password=' keyword as well: the value is whitespace-delimited
(or single-quoted, honoring backslash escapes) and ends at the closing
brace of the pqopt block.  Use it to redact the pqopt value where
copyConnAttributes logs it, and skip the generic raw logging for that
key.  Non-secret pqopt fields (host, sslmode, application_name, ...)
remain visible for debugging.

Verified against PostgreSQL 18: ODBC PWD, unquoted pqopt password and
single-quoted pqopt password are all masked; no cleartext remains.
@davecramer davecramer changed the title Redact the DB password in connection strings written to the debug log Redact the DB password (ODBC PWD and libpq pqopt password) in debug logs Aug 28, 2026
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