Skip to content

Redact password from DatabaseSessionService engine-creation errors - #6485

Open
herdiyana256 wants to merge 3 commits into
google:mainfrom
herdiyana256:redact-db-url-password-in-errors
Open

Redact password from DatabaseSessionService engine-creation errors#6485
herdiyana256 wants to merge 3 commits into
google:mainfrom
herdiyana256:redact-db-url-password-in-errors

Conversation

@herdiyana256

Copy link
Copy Markdown

DatabaseSessionService.init includes the database URL in the ValueError it raises when engine creation fails. There are three such messages: one for an invalid URL argument (ArgumentError), one for a missing driver module (ImportError), and a generic one for any other failure. Each interpolated the raw db_url directly into the message text.

A SQLAlchemy URL for a networked backend carries the password inline, for example postgresql+asyncpg://user:password@host/db. As a result, any of these failures surfaces the database password verbatim in the exception and in any logs that record it. The most common trigger is entirely benign: configuring a Postgres or MySQL URL without having installed the corresponding async driver raises the ImportError branch, which then prints the full URL including the password. The underlying SQLAlchemy exceptions in these paths do not contain the password, so the disclosure is introduced solely by these messages.

This change renders the URL with hide_password=True before including it in the messages, so the password is replaced with *** while the dialect, host, and database remain visible for debugging. When the URL cannot be parsed at all, it falls back to a redacted placeholder rather than echoing the raw string.

Verified against the current published class: before the change, instantiating DatabaseSessionService with a password-bearing Postgres URL whose driver is not installed raises ... 'postgresql+asyncpg://admin:SUPER_SECRET_PW@db.internal:5432/prod' with the password in clear text; after the change the same call reports ...admin:***@db.internal:5432/prod and the password no longer appears in the error for any of the three branches.

@adk-bot adk-bot added the services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc label Jul 26, 2026
DatabaseSessionService.__init__ embedded the raw db_url in three ValueError
messages raised when engine creation fails (invalid URL argument, missing
driver module, or any other error). A SQLAlchemy URL for a networked backend
carries the password inline, e.g. postgresql+asyncpg://user:password@host/db,
so any of these failures (for example a driver that is not installed) surfaced
the database password verbatim in the exception and in any logs that record it.

Render the URL with hide_password=True before including it in the messages,
falling back to a redacted placeholder when the URL cannot be parsed. The
messages keep the useful dialect/host/database context while no longer exposing
the password.
@rohityan
rohityan force-pushed the redact-db-url-password-in-errors branch from d343b44 to c229b01 Compare July 27, 2026 21:25
@rohityan rohityan added the request clarification [Status] The maintainer need clarification or more information from the author label Jul 27, 2026
@rohityan

Copy link
Copy Markdown
Collaborator

Hi @herdiyana256 , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Can you please add a unit test verifying that _redact_db_url masks passwords and that DatabaseSessionService.__init__ exceptions do not expose credentials.
Also can you please fix the failing ci tests.

@herdiyana256

Copy link
Copy Markdown
Author

Thanks @rohityan! Added unit tests in tests/unittests/sessions/test_session_service.py:

  • test_redact_db_url_masks_embedded_password and test_redact_db_url_falls_back_to_placeholder_for_unparsable_url cover _redact_db_url directly — the password is stripped while host/database/user are kept, and unparsable URLs fall back to [redacted].
  • test_database_session_service_init_error_does_not_leak_password (parametrized over ArgumentError, ImportError, and a generic error) asserts the ValueError raised from DatabaseSessionService.__init__ never contains the URL password, while still keeping the host so the message stays actionable.

All pass locally (pytest tests/unittests/sessions/test_session_service.py), and the branch is rebased on latest main with CLA/checks green. PTAL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

request clarification [Status] The maintainer need clarification or more information from the author services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants