Skip to content

🛡️ Sentinel: [MEDIUM] Fix log injection vulnerabilities#122

Merged
abhimehro merged 5 commits intomainfrom
sentinel/fix-log-injection-768802791969432720
Jan 27, 2026
Merged

🛡️ Sentinel: [MEDIUM] Fix log injection vulnerabilities#122
abhimehro merged 5 commits intomainfrom
sentinel/fix-log-injection-768802791969432720

Conversation

@google-labs-jules
Copy link

  • 🚨 Severity: MEDIUM (Terminal Log Injection)
  • 💡 Vulnerability: User-controlled inputs (folder names from JSON, error messages) were logged directly using f-strings. This allowed malicious JSON sources to inject ANSI escape sequences, potentially corrupting terminal output or spoofing logs.
  • 🎯 Impact: Terminal hijacking or log spoofing.
  • 🔧 Fix: Applied sanitize_for_log (which uses repr() to escape control characters) to the missing call sites. Added regression test.
  • ✅ Verification: Ran uv run pytest tests/test_log_sanitization.py. All tests passed.

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

Fixed missing sanitization in logging calls where user-controlled input (folder names, errors) was interpolated directly. This prevents Terminal Escape Sequence Injection.

Added regression test `tests/test_log_sanitization.py`.
Updated `sanitize_for_log` documentation.
@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 22, 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.

**Prevention:**
1. Always use `if not ip.is_global or ip.is_multicast:` for strict SSRF filtering, rather than manual blacklists of private ranges.

## 2026-05-18 - [Log Injection via Unsanitized Input]

Check notice

Code scanning / Remark-lint (reported by Codacy)

Warn when shortcut reference links are used.

[no-shortcut-reference-link] Use the trailing `[]` on reference links
**Prevention:**
1. Always use `if not ip.is_global or ip.is_multicast:` for strict SSRF filtering, rather than manual blacklists of private ranges.

## 2026-05-18 - [Log Injection via Unsanitized Input]

Check notice

Code scanning / Remark-lint (reported by Codacy)

Warn when references to undefined definitions are found.

[no-undefined-references] Found reference to undefined definition
if attempt < MAX_RETRIES:
wait_time = FOLDER_CREATION_DELAY * (attempt + 1)
log.info(f"Folder '{name}' not found yet. Retrying in {wait_time}s...")
log.info(f"Folder '{sanitize_for_log(name)}' not found yet. Retrying in {wait_time}s...")

Check warning

Code scanning / Prospector (reported by Codacy)

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

Use lazy % formatting in logging functions (logging-fstring-interpolation)
success_count += 1
except Exception as e:
log.error(f"Failed to process folder '{folder_name}': {e}")
log.error(f"Failed to process folder '{sanitize_for_log(folder_name)}': {sanitize_for_log(e)}")

Check warning

Code scanning / Prospector (reported by Codacy)

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

Use lazy % formatting in logging functions (logging-fstring-interpolation)
@@ -0,0 +1,88 @@
import unittest
from unittest.mock import MagicMock, patch
import sys

Check warning

Code scanning / Prospector (reported by Codacy)

Unused import sys (unused-import)

Unused import sys (unused-import)
import unittest
from unittest.mock import MagicMock, patch
import sys
import os

Check warning

Code scanning / Prospector (reported by Codacy)

Unused import os (unused-import)

Unused import os (unused-import)
@patch('main.time.sleep')
@patch('main._api_post')
@patch('main._api_get')
def test_create_folder_logs_unsafe_name(self, mock_get, mock_post, mock_sleep, mock_log):

Check warning

Code scanning / Prospector (reported by Codacy)

Unused argument 'mock_sleep' (unused-argument)

Unused argument 'mock_sleep' (unused-argument)
# But wait, if the source is f"Folder '{name}'...", logging receives the formatted string.
log_msg = args[0]
if unsafe_name in log_msg:
found_raw = True

Check warning

Code scanning / Prospector (reported by Codacy)

over-indented (E117)

over-indented (E117)
# But wait, if the source is f"Folder '{name}'...", logging receives the formatted string.
log_msg = args[0]
if unsafe_name in log_msg:
found_raw = True

Check warning

Code scanning / Prospector (reported by Codacy)

Bad indentation. Found 17 spaces, expected 16 (bad-indentation)

Bad indentation. Found 17 spaces, expected 16 (bad-indentation)
if unsafe_name in log_msg:
found_raw = True
if sanitized_name in log_msg:
found_sanitized = True

Check warning

Code scanning / Prospector (reported by Codacy)

over-indented (E117)

over-indented (E117)
if unsafe_name in log_msg:
found_raw = True
if sanitized_name in log_msg:
found_sanitized = True

Check warning

Code scanning / Prospector (reported by Codacy)

Bad indentation. Found 17 spaces, expected 16 (bad-indentation)

Bad indentation. Found 17 spaces, expected 16 (bad-indentation)
self.assertTrue(found_sanitized, "Should find sanitized name in logs")
self.assertFalse(found_raw, "Should not find raw name in logs")

if __name__ == '__main__':

Check warning

Code scanning / Prospector (reported by Codacy)

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

expected 2 blank lines after class or function definition, found 1 (E305)
if attempt < MAX_RETRIES:
wait_time = FOLDER_CREATION_DELAY * (attempt + 1)
log.info(f"Folder '{name}' not found yet. Retrying in {wait_time}s...")
log.info(f"Folder '{sanitize_for_log(name)}' not found yet. Retrying in {wait_time}s...")

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Line too long (105/100)

Line too long (105/100)
success_count += 1
except Exception as e:
log.error(f"Failed to process folder '{folder_name}': {e}")
log.error(f"Failed to process folder '{sanitize_for_log(folder_name)}': {sanitize_for_log(e)}")

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Line too long (119/100)

Line too long (119/100)
@@ -0,0 +1,88 @@
import unittest

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing module docstring

Missing module docstring
import os
import main

class TestLogSanitization(unittest.TestCase):

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing class docstring

Missing class docstring
args = call[0]
# Since it is an f-string in the source, we can't easily check format args.
# We have to check the string content.
# But wait, if the source is f"Folder '{name}'...", logging receives the formatted string.

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Line too long (102/100)

Line too long (102/100)
import unittest
from unittest.mock import MagicMock, patch
import sys
import os

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Unused import os

Unused import os
@patch('main.time.sleep')
@patch('main._api_post')
@patch('main._api_get')
def test_create_folder_logs_unsafe_name(self, mock_get, mock_post, mock_sleep, mock_log):

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Unused argument 'mock_sleep'

Unused argument 'mock_sleep'

# Check logs
# We look for the specific log message: "Folder '{name}' not found yet..."
found_unsafe_log = False

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Unused variable 'found_unsafe_log'

Unused variable 'found_unsafe_log'
# But wait, if the source is f"Folder '{name}'...", logging receives the formatted string.
log_msg = args[0]
if unsafe_name in log_msg:
found_raw = True

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Bad indentation. Found 17 spaces, expected 16

Bad indentation. Found 17 spaces, expected 16
if unsafe_name in log_msg:
found_raw = True
if sanitized_name in log_msg:
found_sanitized = True

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Bad indentation. Found 17 spaces, expected 16

Bad indentation. Found 17 spaces, expected 16
if attempt < MAX_RETRIES:
wait_time = FOLDER_CREATION_DELAY * (attempt + 1)
log.info(f"Folder '{name}' not found yet. Retrying in {wait_time}s...")
log.info(f"Folder '{sanitize_for_log(name)}' not found yet. Retrying in {wait_time}s...")

Check warning

Code scanning / Pylint (reported by Codacy)

Line too long (105/100)

Line too long (105/100)
success_count += 1
except Exception as e:
log.error(f"Failed to process folder '{folder_name}': {e}")
log.error(f"Failed to process folder '{sanitize_for_log(folder_name)}': {sanitize_for_log(e)}")

Check warning

Code scanning / Pylint (reported by Codacy)

Line too long (119/100)

Line too long (119/100)
@@ -0,0 +1,88 @@
import unittest

Check warning

Code scanning / Pylint (reported by Codacy)

Missing module docstring

Missing module docstring
import os
import main

class TestLogSanitization(unittest.TestCase):

Check warning

Code scanning / Pylint (reported by Codacy)

Missing class docstring

Missing class docstring
@patch('main.time.sleep')
@patch('main._api_post')
@patch('main._api_get')
def test_create_folder_logs_unsafe_name(self, mock_get, mock_post, mock_sleep, mock_log):

Check warning

Code scanning / Pylint (reported by Codacy)

Too many local variables (16/15)

Too many local variables (16/15)
import unittest
from unittest.mock import MagicMock, patch
import sys
import os

Check notice

Code scanning / Pylint (reported by Codacy)

Unused import os

Unused import os
@patch('main.time.sleep')
@patch('main._api_post')
@patch('main._api_get')
def test_create_folder_logs_unsafe_name(self, mock_get, mock_post, mock_sleep, mock_log):

Check notice

Code scanning / Pylint (reported by Codacy)

Unused argument 'mock_sleep'

Unused argument 'mock_sleep'

# Check logs
# We look for the specific log message: "Folder '{name}' not found yet..."
found_unsafe_log = False

Check notice

Code scanning / Pylint (reported by Codacy)

Unused variable 'found_unsafe_log'

Unused variable 'found_unsafe_log'
# But wait, if the source is f"Folder '{name}'...", logging receives the formatted string.
log_msg = args[0]
if unsafe_name in log_msg:
found_raw = True

Check notice

Code scanning / Pylint (reported by Codacy)

Bad indentation. Found 17 spaces, expected 16

Bad indentation. Found 17 spaces, expected 16
if unsafe_name in log_msg:
found_raw = True
if sanitized_name in log_msg:
found_sanitized = True

Check notice

Code scanning / Pylint (reported by Codacy)

Bad indentation. Found 17 spaces, expected 16

Bad indentation. Found 17 spaces, expected 16
@abhimehro abhimehro marked this pull request as ready for review January 22, 2026 11:07
Copilot AI review requested due to automatic review settings January 22, 2026 11:07
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.

Pull request overview

This PR fixes log injection vulnerabilities where user-controlled inputs (folder names from JSON and error messages) were logged without sanitization, potentially allowing terminal escape sequence injection.

Changes:

  • Enhanced sanitize_for_log function documentation to clarify control character escaping
  • Applied sanitize_for_log to folder names and error messages in two critical log call sites
  • Added comprehensive regression tests to verify the fix

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
main.py Added sanitization to folder name logging in create_folder and error logging in sync_profile
tests/test_log_sanitization.py Added new test suite with ANSI escape sequence injection tests
.jules/sentinel.md Documented the vulnerability and prevention strategy

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

abhimehro and others added 4 commits January 22, 2026 05:35
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@abhimehro abhimehro merged commit 3d951c2 into main Jan 27, 2026
8 checks passed
@abhimehro abhimehro deleted the sentinel/fix-log-injection-768802791969432720 branch January 27, 2026 12:16
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