Skip to content

fix: redact secret tokens from URLs before logging#197

Closed
ds-bastianne wants to merge 1 commit into
DasBasti:mainfrom
ds-bastianne:claude/autopatch-scan-4257bb84-vuln-1318600-MXxOI
Closed

fix: redact secret tokens from URLs before logging#197
ds-bastianne wants to merge 1 commit into
DasBasti:mainfrom
ds-bastianne:claude/autopatch-scan-4257bb84-vuln-1318600-MXxOI

Conversation

@ds-bastianne

@ds-bastianne ds-bastianne commented Jun 1, 2026

Copy link
Copy Markdown

Login/OAuth tokens (login_token, access_token, refresh_token) appear in URL query strings and fragments during the auth flow. The httpx event hooks (log_request, log_response, raise_for_status_handler) logged these URLs verbatim at DEBUG and ERROR levels, leaking live credentials to log files.

Add sanitize_url() to log_sanitizer.py that strips sensitive query and fragment parameters. Apply it to all URL logging in authentication.py (SmartLoginClient, SmartLoginRetry, SmartAuthentication.async_auth_flow) and client.py (SmartClient). Also extend sanitize_string to catch param=value and glt= patterns in arbitrary text.

https://claude.ai/code/session_01TFLXNPgy1T5kvNaBB6VUx7

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Enhanced log sanitization to prevent exposure of sensitive information (API credentials, tokens, and query parameters) in application logs.

Login/OAuth tokens (login_token, access_token, refresh_token) appear in
URL query strings and fragments during the auth flow. The httpx event
hooks (log_request, log_response, raise_for_status_handler) logged these
URLs verbatim at DEBUG and ERROR levels, leaking live credentials to log
files.

Add sanitize_url() to log_sanitizer.py that strips sensitive query and
fragment parameters. Apply it to all URL logging in authentication.py
(SmartLoginClient, SmartLoginRetry, SmartAuthentication.async_auth_flow)
and client.py (SmartClient). Also extend _sanitize_string to catch
param=value and glt_<key>=<token> patterns in arbitrary text.

https://claude.ai/code/session_01TFLXNPgy1T5kvNaBB6VUx7
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds URL-based log sanitization across authentication and HTTP client logging. A new sanitize_url() function redacts sensitive query and fragment parameters, reducing exposure of API keys and tokens in logs. The sanitization logic is applied to request/response debugging and error handling throughout SmartAuthentication, SmartLoginClient, SmartLoginRetry, and SmartClient.

Changes

URL Sanitization Across Logging

Layer / File(s) Summary
URL sanitization primitives and patterns
pysmarthashtag/api/log_sanitizer.py
Introduces URL parsing imports, SENSITIVE_URL_PARAMS set, regex patterns for detecting sensitive parameters and glt_<apikey>=<value> tokens, the sanitize_url() function with URL reconstruction, and extends _sanitize_string() to mask embedded URL parameter patterns in arbitrary strings.
Authentication logging sanitization
pysmarthashtag/api/authentication.py
Imports sanitize_url and applies it across SmartAuthentication, SmartLoginClient, and SmartLoginRetry: request/response debug logs now emit sanitized URLs, error logs redact request URLs and exception text.
HTTP client request/response logging sanitization
pysmarthashtag/api/client.py
Imports sanitize_url and updates SmartClient's HTTP event hooks to log sanitized request URLs instead of raw URLs in debug messages.

🎯 2 (Simple) | ⏱️ ~12 minutes

🐰 In logs where secrets hide and URLs shine bright,
We mask the keys and tokens from the prying light,
With patterns matched and queries scrubbed clean,
The safest logs you ever have seen! 🔐✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main objective of the changeset: redacting secret tokens from URLs before logging. It directly reflects the core purpose of adding URL sanitization across authentication and client modules.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pysmarthashtag/api/authentication.py (1)

248-250: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Sanitize the non-rate-limit login failure log too.

This branch still logs exc raw. For httpx.HTTPStatusError, that string includes the request URL, so context / login_token can still hit logs through this path even after the new sanitization changes.

Suggested fix
         else:
             self._state.quiet_until = now + self._OTHER_FAILURE_BACKOFF
             _LOGGER.info(
                 "Smart API login failed (%s). Short retry-suppress until %s",
-                exc,
+                sanitize_log_data(str(exc)),
                 self._state.quiet_until.isoformat(timespec="seconds"),
             )

As per coding guidelines, "Use sanitize_log_data() from api.log_sanitizer when logging sensitive data".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pysmarthashtag/api/authentication.py` around lines 248 - 250, The info log in
the login-failure branch currently interpolates exc directly (in the
_LOGGER.info call), which may leak request URLs for httpx.HTTPStatusError;
update that call to sanitize the exception data using sanitize_log_data() from
api.log_sanitizer before logging (e.g., wrap or convert exc via
sanitize_log_data(exc) or extract and sanitize only non-sensitive fields),
ensuring the _LOGGER.info invocation that references exc uses the sanitized
value; touch the code around the login retry-suppress branch (where _LOGGER.info
is called) and keep the existing message text/format but pass the sanitized
exception instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pysmarthashtag/api/log_sanitizer.py`:
- Around line 58-63: The regex _URL_PARAM_PATTERN currently only matches params
preceded by ? or &, so fragment-leading (`#access_token`=...) and standalone
"access_token=..." cases slip through; update _URL_PARAM_PATTERN to also accept
start-of-string, fragment '#' or word-boundary prefixes (so keys preceded by ^,
#, ?, &, or a word boundary are matched) while preserving the same capture
groups and flags, then run/update tests and ensure _sanitize_string uses the
updated pattern to redact those additional cases.

---

Outside diff comments:
In `@pysmarthashtag/api/authentication.py`:
- Around line 248-250: The info log in the login-failure branch currently
interpolates exc directly (in the _LOGGER.info call), which may leak request
URLs for httpx.HTTPStatusError; update that call to sanitize the exception data
using sanitize_log_data() from api.log_sanitizer before logging (e.g., wrap or
convert exc via sanitize_log_data(exc) or extract and sanitize only
non-sensitive fields), ensuring the _LOGGER.info invocation that references exc
uses the sanitized value; touch the code around the login retry-suppress branch
(where _LOGGER.info is called) and keep the existing message text/format but
pass the sanitized exception instead.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c1c2e8dd-d635-4ba4-bf74-ec77d16ad71f

📥 Commits

Reviewing files that changed from the base of the PR and between 7f5e2d5 and fe256b0.

📒 Files selected for processing (3)
  • pysmarthashtag/api/authentication.py
  • pysmarthashtag/api/client.py
  • pysmarthashtag/api/log_sanitizer.py

Comment on lines +58 to +63
# Matches sensitive key=value pairs in query strings embedded in text (e.g. login_token=abc123&)
_URL_PARAM_PATTERN = re.compile(
r"(?<=[?&])((?:access_token|refresh_token|login_token|token|code|context)"
r")=([^&#\s]+)",
re.IGNORECASE,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle fragment-leading and standalone secret params in _sanitize_string.

_URL_PARAM_PATTERN only matches keys preceded by ? or &. Strings like #access_token=... or access_token=... still pass through unchanged, so the fallback sanitize_log_data(str(exc)) path can leak the first OAuth token in fragment/query-like text.

Suggested fix
 _URL_PARAM_PATTERN = re.compile(
-    r"(?<=[?&])((?:access_token|refresh_token|login_token|token|code|context)"
-    r")=([^&#\s]+)",
+    r"(^|[?#&])((?:access_token|refresh_token|login_token|token|code|context))=([^&#\s]+)",
     re.IGNORECASE,
 )
-    result = _URL_PARAM_PATTERN.sub(r"\1=***", result)
+    result = _URL_PARAM_PATTERN.sub(r"\1\2=***", result)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pysmarthashtag/api/log_sanitizer.py` around lines 58 - 63, The regex
_URL_PARAM_PATTERN currently only matches params preceded by ? or &, so
fragment-leading (`#access_token`=...) and standalone "access_token=..." cases
slip through; update _URL_PARAM_PATTERN to also accept start-of-string, fragment
'#' or word-boundary prefixes (so keys preceded by ^, #, ?, &, or a word
boundary are matched) while preserving the same capture groups and flags, then
run/update tests and ensure _sanitize_string uses the updated pattern to redact
those additional cases.

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

An unexpected error occurred while generating fixes: Not Found - https://docs.github.com/rest/git/refs#get-a-reference

@DasBasti

DasBasti commented Jun 7, 2026

Copy link
Copy Markdown
Owner

@

@DasBasti DasBasti closed this Jun 7, 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.

3 participants