Skip to content

🛡️ Sentinel: [MEDIUM] Fix sensitive data leak in debug logs#126

Merged
abhimehro merged 1 commit intomainfrom
sentinel-log-hardening-9089717741045128790
Jan 27, 2026
Merged

🛡️ Sentinel: [MEDIUM] Fix sensitive data leak in debug logs#126
abhimehro merged 1 commit intomainfrom
sentinel-log-hardening-9089717741045128790

Conversation

@google-labs-jules
Copy link

🛡️ Sentinel: [MEDIUM] Fix sensitive data leak in debug logs

🚨 Severity: MEDIUM
💡 Vulnerability: API response bodies containing secrets (e.g. tokens in error messages) were logged in plain text when debug logging was enabled.
🎯 Impact: Potential leakage of API tokens or PII to log files.
🔧 Fix: Applied sanitize_for_log redaction to debug log outputs.
✨ Enhancement: Also hardened HTTP client by disabling redirects and adding User-Agent.
✅ Verification: Added tests/test_security_hardening.py verifying redaction and client config.


PR created automatically by Jules for task 9089717741045128790 started by @abhimehro

@google-labs-jules
Copy link
Author

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@trunk-io
Copy link

trunk-io bot commented Jan 23, 2026

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.


def test_retry_request_sanitizes_token_in_debug_logs(caplog):
# Setup sensitive data
sensitive_token = "SECRET_TOKEN_123"

Check notice

Code scanning / Bandit

Possible hardcoded password: 'SECRET_TOKEN_123' Note test

Possible hardcoded password: 'SECRET_TOKEN_123'
main._retry_request(mock_func, max_retries=1, delay=0)

# Check logs
assert "Response content:" in caplog.text

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

# Check logs
assert "Response content:" in caplog.text
assert sensitive_token not in caplog.text

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Check logs
assert "Response content:" in caplog.text
assert sensitive_token not in caplog.text
assert "[REDACTED]" in caplog.text

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

def test_push_rules_sanitizes_token_in_debug_logs(caplog):
# Setup sensitive data
sensitive_token = "SECRET_TOKEN_456"

Check notice

Code scanning / Bandit

Possible hardcoded password: 'SECRET_TOKEN_456' Note test

Possible hardcoded password: 'SECRET_TOKEN_456'

with main._api_client() as client:
# Check User-Agent
assert client.headers["User-Agent"] == "Control-D-Sync/0.1.0"

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Check User-Agent
assert client.headers["User-Agent"] == "Control-D-Sync/0.1.0"
# Check Authorization
assert client.headers["Authorization"] == "Bearer test_token"

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Check Authorization
assert client.headers["Authorization"] == "Bearer test_token"
# Check follow_redirects (in httpx < 0.20 it was allow_redirects, now follow_redirects)
assert client.follow_redirects is False

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
def test_gh_client_configuration():
client = main._gh
# Check User-Agent
assert client.headers["User-Agent"] == "Control-D-Sync/0.1.0"

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Check User-Agent
assert client.headers["User-Agent"] == "Control-D-Sync/0.1.0"
# Check follow_redirects
assert client.follow_redirects is False

Check notice

Code scanning / Bandit

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
1. Implement strict validation on all data items from external lists (`is_valid_rule`).
2. Filter out items containing dangerous characters (`<`, `>`, `"` etc.) or control codes.

## 2026-05-15 - [Inconsistent Redaction in Debug Logs]

Check notice

Code scanning / Remark-lint (reported by Codacy)

Warn when references to undefined definitions are found. Note

[no-undefined-references] Found reference to undefined definition
1. Implement strict validation on all data items from external lists (`is_valid_rule`).
2. Filter out items containing dangerous characters (`<`, `>`, `"` etc.) or control codes.

## 2026-05-15 - [Inconsistent Redaction in Debug Logs]

Check notice

Code scanning / Remark-lint (reported by Codacy)

Warn when shortcut reference links are used. Note

[no-shortcut-reference-link] Use the trailing [] on reference links
)

_gh = httpx.Client(timeout=30)
_gh = httpx.Client(

Check warning

Code scanning / Prospector (reported by Codacy)

expected 2 blank lines after class or function definition, found 1 (E305) Warning

expected 2 blank lines after class or function definition, found 1 (E305)
if attempt == max_retries - 1:
if hasattr(e, 'response') and e.response is not None:
log.debug(f"Response content: {e.response.text}")
log.debug(f"Response content: {sanitize_for_log(e.response.text)}")

Check warning

Code scanning / Prospector (reported by Codacy)

Use lazy % formatting in logging functions (logging-fstring-interpolation) Warning

Use lazy % formatting in logging functions (logging-fstring-interpolation)
log.error(f"Failed to push batch {batch_idx} for folder {sanitize_for_log(folder_name)}: {sanitize_for_log(e)}")
if hasattr(e, 'response') and e.response is not None:
log.debug(f"Response content: {e.response.text}")
log.debug(f"Response content: {sanitize_for_log(e.response.text)}")

Check warning

Code scanning / Prospector (reported by Codacy)

Use lazy % formatting in logging functions (logging-fstring-interpolation) Warning

Use lazy % formatting in logging functions (logging-fstring-interpolation)
@@ -0,0 +1,95 @@
import logging
import pytest

Check warning

Code scanning / Prospector (reported by Codacy)

Unable to import 'pytest' (import-error) Warning test

Unable to import 'pytest' (import-error)
import logging
import pytest
from unittest.mock import MagicMock, patch
import httpx

Check warning

Code scanning / Prospector (reported by Codacy)

Unable to import 'httpx' (import-error) Warning test

Unable to import 'httpx' (import-error)
# Call _retry_request (it re-raises the exception)
with pytest.raises(httpx.HTTPError):
# Set retries to 1 to fail fast
main._retry_request(mock_func, max_retries=1, delay=0)

Check warning

Code scanning / Prospector (reported by Codacy)

Access to a protected member _retry_request of a client class (protected-access) Warning test

Access to a protected member _retry_request of a client class (protected-access)
# Setup token
main.TOKEN = "test_token"

with main._api_client() as client:

Check warning

Code scanning / Prospector (reported by Codacy)

Access to a protected member _api_client of a client class (protected-access) Warning test

Access to a protected member _api_client of a client class (protected-access)
assert client.follow_redirects is False

def test_gh_client_configuration():
client = main._gh

Check warning

Code scanning / Prospector (reported by Codacy)

Access to a protected member _gh of a client class (protected-access) Warning test

Access to a protected member _gh of a client class (protected-access)
)

_gh = httpx.Client(timeout=30)
_gh = httpx.Client(

Check warning

Code scanning / Pylint (reported by Codacy)

Constant name "_gh" doesn't conform to UPPER_CASE naming style Warning

Constant name "_gh" doesn't conform to UPPER_CASE naming style
@@ -0,0 +1,95 @@
import logging

Check warning

Code scanning / Pylint (reported by Codacy)

Missing module docstring Warning test

Missing module docstring
@@ -0,0 +1,95 @@
import logging
import pytest
from unittest.mock import MagicMock, patch

Check warning

Code scanning / Pylint (reported by Codacy)

standard import "from unittest.mock import MagicMock, patch" should be placed before "import pytest" Warning test

standard import "from unittest.mock import MagicMock, patch" should be placed before "import pytest"
import main

# Mock httpx.HTTPError to include a response with sensitive data
def create_mock_error(status_code, text, request_url="https://example.com"):

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning test

Missing function docstring
response.request.url = request_url

# Use HTTPStatusError which accepts request and response
error = httpx.HTTPStatusError(f"HTTP Error {status_code}", request=response.request, response=response)

Check warning

Code scanning / Pylint (reported by Codacy)

Line too long (107/100) Warning test

Line too long (107/100)
assert sensitive_token not in caplog.text
assert "[REDACTED]" in caplog.text

def test_api_client_configuration():

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning test

Missing function docstring
# Check follow_redirects (in httpx < 0.20 it was allow_redirects, now follow_redirects)
assert client.follow_redirects is False

def test_gh_client_configuration():

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring Warning test

Missing function docstring
# Call _retry_request (it re-raises the exception)
with pytest.raises(httpx.HTTPError):
# Set retries to 1 to fail fast
main._retry_request(mock_func, max_retries=1, delay=0)

Check notice

Code scanning / Pylint (reported by Codacy)

Access to a protected member _retry_request of a client class Note test

Access to a protected member _retry_request of a client class
# Setup token
main.TOKEN = "test_token"

with main._api_client() as client:

Check notice

Code scanning / Pylint (reported by Codacy)

Access to a protected member _api_client of a client class Note test

Access to a protected member _api_client of a client class
assert client.follow_redirects is False

def test_gh_client_configuration():
client = main._gh

Check notice

Code scanning / Pylint (reported by Codacy)

Access to a protected member _gh of a client class Note test

Access to a protected member _gh of a client class
main._retry_request(mock_func, max_retries=1, delay=0)

# Check logs
assert "Response content:" in caplog.text

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

# Check logs
assert "Response content:" in caplog.text
assert sensitive_token not in caplog.text

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Check logs
assert "Response content:" in caplog.text
assert sensitive_token not in caplog.text
assert "[REDACTED]" in caplog.text

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
)

# push_rules catches the error and returns False (or continues if batch failed)
assert res is False

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
assert res is False

# Check logs
assert "Response content:" in caplog.text

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.

with main._api_client() as client:
# Check User-Agent
assert client.headers["User-Agent"] == "Control-D-Sync/0.1.0"

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Check User-Agent
assert client.headers["User-Agent"] == "Control-D-Sync/0.1.0"
# Check Authorization
assert client.headers["Authorization"] == "Bearer test_token"

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Check Authorization
assert client.headers["Authorization"] == "Bearer test_token"
# Check follow_redirects (in httpx < 0.20 it was allow_redirects, now follow_redirects)
assert client.follow_redirects is False

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
def test_gh_client_configuration():
client = main._gh
# Check User-Agent
assert client.headers["User-Agent"] == "Control-D-Sync/0.1.0"

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
# Check User-Agent
assert client.headers["User-Agent"] == "Control-D-Sync/0.1.0"
# Check follow_redirects
assert client.follow_redirects is False

Check notice

Code scanning / Bandit (reported by Codacy)

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test

Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
@@ -0,0 +1,95 @@
import logging

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing module docstring Warning test

Missing module docstring
@@ -0,0 +1,95 @@
import logging
import pytest
from unittest.mock import MagicMock, patch

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

standard import "from unittest.mock import MagicMock, patch" should be placed before "import pytest" Warning test

standard import "from unittest.mock import MagicMock, patch" should be placed before "import pytest"
import main

# Mock httpx.HTTPError to include a response with sensitive data
def create_mock_error(status_code, text, request_url="https://example.com"):

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing function or method docstring Warning test

Missing function or method docstring
response.request.url = request_url

# Use HTTPStatusError which accepts request and response
error = httpx.HTTPStatusError(f"HTTP Error {status_code}", request=response.request, response=response)

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Line too long (107/100) Warning test

Line too long (107/100)
error = httpx.HTTPStatusError(f"HTTP Error {status_code}", request=response.request, response=response)
return error

def test_retry_request_sanitizes_token_in_debug_logs(caplog):

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing function or method docstring Warning test

Missing function or method docstring
if attempt == max_retries - 1:
if hasattr(e, 'response') and e.response is not None:
log.debug(f"Response content: {e.response.text}")
log.debug(f"Response content: {sanitize_for_log(e.response.text)}")

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Use lazy % formatting in logging functions Note

Use lazy % formatting in logging functions
log.error(f"Failed to push batch {batch_idx} for folder {sanitize_for_log(folder_name)}: {sanitize_for_log(e)}")
if hasattr(e, 'response') and e.response is not None:
log.debug(f"Response content: {e.response.text}")
log.debug(f"Response content: {sanitize_for_log(e.response.text)}")

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Use lazy % formatting in logging functions Note

Use lazy % formatting in logging functions
# Call _retry_request (it re-raises the exception)
with pytest.raises(httpx.HTTPError):
# Set retries to 1 to fail fast
main._retry_request(mock_func, max_retries=1, delay=0)

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Access to a protected member _retry_request of a client class Note test

Access to a protected member _retry_request of a client class
# Setup token
main.TOKEN = "test_token"

with main._api_client() as client:

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Access to a protected member _api_client of a client class Note test

Access to a protected member _api_client of a client class
assert client.follow_redirects is False

def test_gh_client_configuration():
client = main._gh

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Access to a protected member _gh of a client class Note test

Access to a protected member _gh of a client class
@abhimehro abhimehro marked this pull request as ready for review January 27, 2026 07:24
Copilot AI review requested due to automatic review settings January 27, 2026 07:24
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@abhimehro abhimehro merged commit 3f2d4aa into main Jan 27, 2026
18 checks passed
@abhimehro abhimehro deleted the sentinel-log-hardening-9089717741045128790 branch January 27, 2026 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants