-
Notifications
You must be signed in to change notification settings - Fork 1
π‘οΈ Sentinel: [MEDIUM] Fix log injection vulnerabilities #122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f0f016d
0f687d3
53f67b0
6f77de7
3d951c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| import unittest | ||
Check warningCode scanning / Pylintpython3 (reported by Codacy) Missing module docstring
Missing module docstring
Check warningCode scanning / Pylint (reported by Codacy) Missing module docstring
Missing module docstring
|
||
| from unittest.mock import MagicMock, patch | ||
| import main | ||
|
|
||
| class TestLogSanitization(unittest.TestCase): | ||
Check warningCode scanning / Pylintpython3 (reported by Codacy) Missing class docstring
Missing class docstring
Check warningCode scanning / Pylint (reported by Codacy) Missing class docstring
Missing class docstring
|
||
| def test_sanitize_for_log_escapes_ansi(self): | ||
| """Test that sanitize_for_log escapes ANSI characters.""" | ||
| # ANSI Red color | ||
| malicious_input = "\x1b[31mMalicious" | ||
| sanitized = main.sanitize_for_log(malicious_input) | ||
|
|
||
| # repr() escapes \x1b as \x1b (4 chars: \, x, 1, b) | ||
| # So the output string should contain literal backslash | ||
| self.assertIn("\\x1b", sanitized) | ||
| # It should NOT contain the actual escape character | ||
| self.assertNotIn("\x1b", sanitized) | ||
|
|
||
| @patch('main.log') | ||
| @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 warningCode scanning / Prospector (reported by Codacy) Unused argument 'mock_sleep' (unused-argument)
Unused argument 'mock_sleep' (unused-argument)
Check warningCode scanning / Pylint (reported by Codacy) Too many local variables (16/15)
Too many local variables (16/15)
Check noticeCode scanning / Pylintpython3 (reported by Codacy) Unused argument 'mock_sleep'
Unused argument 'mock_sleep'
Check noticeCode scanning / Pylint (reported by Codacy) Unused argument 'mock_sleep'
Unused argument 'mock_sleep'
|
||
| """ | ||
| Verify that create_folder logs the raw name if not sanitized. | ||
| We expect this to FAIL (or show raw usage) before the fix. | ||
| """ | ||
| # Setup | ||
| main.MAX_RETRIES = 1 | ||
| main.FOLDER_CREATION_DELAY = 0 | ||
|
|
||
| # Mock POST to succeed (returns None, assuming polling needed if direct ID missing) | ||
| mock_post.return_value.json.return_value = {"body": {"group": {"something": "else"}}} | ||
|
|
||
| # Mock GET to return empty groups (fail to find) | ||
| mock_get.return_value.json.return_value = {"body": {"groups": []}} | ||
|
|
||
| unsafe_name = "\x1b[31mUNSAFE" | ||
|
|
||
| # Call | ||
| client = MagicMock() | ||
| main.create_folder(client, "pid", unsafe_name, 0, 1) | ||
|
|
||
| # Check logs: ensure we do not log the raw unsafe name, but do log the sanitized name. | ||
| # For this test file, I want it to PASS when the code is FIXED. | ||
| # So I should assert that I DO NOT find raw unsafe_name, but I DO find sanitized name. | ||
|
|
||
| sanitized_name = main.sanitize_for_log(unsafe_name) | ||
|
|
||
| found_sanitized = False | ||
| found_raw = False | ||
|
|
||
| for call in mock_log.info.call_args_list: | ||
| 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 warningCode scanning / Pylintpython3 (reported by Codacy) Line too long (102/100)
Line too long (102/100)
Check warningCode scanning / Pylint (reported by Codacy) Line too long (102/100)
Line too long (102/100)
|
||
| log_msg = args[0] | ||
| if unsafe_name in log_msg: | ||
| found_raw = True | ||
| if sanitized_name in log_msg: | ||
| found_sanitized = True | ||
|
|
||
| if found_raw: | ||
| print("VULNERABILITY DETECTED: Raw unsafe name found in logs.") | ||
|
|
||
| # This assertion will FAIL before fix, and PASS after fix. | ||
| 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 warningCode 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)
|
||
| unittest.main() | ||
Check notice
Code scanning / Remark-lint (reported by Codacy)
Warn when shortcut reference links are used.