🛡️ Sentinel: [MEDIUM] Fix log injection vulnerabilities#122
Conversation
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.
|
👋 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 New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
Merging to
|
| **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.
| **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.
| 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)
| 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)
tests/test_log_sanitization.py
Outdated
| @@ -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)
tests/test_log_sanitization.py
Outdated
| 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)
| @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)
tests/test_log_sanitization.py
Outdated
| # 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)
tests/test_log_sanitization.py
Outdated
| # 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)
tests/test_log_sanitization.py
Outdated
| 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)
tests/test_log_sanitization.py
Outdated
| 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)
| 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)
| 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)
| 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)
| @@ -0,0 +1,88 @@ | |||
| import unittest | |||
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Missing module docstring
| import os | ||
| import main | ||
|
|
||
| class TestLogSanitization(unittest.TestCase): |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
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)
tests/test_log_sanitization.py
Outdated
| import unittest | ||
| from unittest.mock import MagicMock, patch | ||
| import sys | ||
| import os |
Check notice
Code scanning / Pylintpython3 (reported by Codacy)
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'
tests/test_log_sanitization.py
Outdated
|
|
||
| # 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'
tests/test_log_sanitization.py
Outdated
| # 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
tests/test_log_sanitization.py
Outdated
| 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
| 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)
| 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)
| @@ -0,0 +1,88 @@ | |||
| import unittest | |||
Check warning
Code scanning / Pylint (reported by Codacy)
Missing module docstring
| import os | ||
| import main | ||
|
|
||
| class TestLogSanitization(unittest.TestCase): |
Check warning
Code scanning / Pylint (reported by Codacy)
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)
tests/test_log_sanitization.py
Outdated
| import unittest | ||
| from unittest.mock import MagicMock, patch | ||
| import sys | ||
| import os |
Check notice
Code scanning / Pylint (reported by Codacy)
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'
tests/test_log_sanitization.py
Outdated
|
|
||
| # 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'
tests/test_log_sanitization.py
Outdated
| # 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
tests/test_log_sanitization.py
Outdated
| 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
There was a problem hiding this comment.
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_logfunction documentation to clarify control character escaping - Applied
sanitize_for_logto 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.
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>
sanitize_for_log(which usesrepr()to escape control characters) to the missing call sites. Added regression test.uv run pytest tests/test_log_sanitization.py. All tests passed.PR created automatically by Jules for task 768802791969432720 started by @abhimehro