-
Notifications
You must be signed in to change notification settings - Fork 1
π‘οΈ Sentinel: [HIGH] Fix SSRF protection by resolving domains #109
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
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,54 @@ | ||
| import unittest | ||
Check warningCode scanning / Pylintpython3 (reported by Codacy) Missing module docstring Warning test
Missing module docstring
Check warningCode scanning / Pylint (reported by Codacy) Missing module docstring Warning test
Missing module docstring
|
||
| from unittest.mock import patch, MagicMock | ||
Check warningCode scanning / Prospector (reported by Codacy) Unused MagicMock imported from unittest.mock (unused-import) Warning test
Unused MagicMock imported from unittest.mock (unused-import)
Check noticeCode scanning / Pylintpython3 (reported by Codacy) Unused MagicMock imported from unittest.mock Note test
Unused MagicMock imported from unittest.mock
Check noticeCode scanning / Pylint (reported by Codacy) Unused MagicMock imported from unittest.mock Note test
Unused MagicMock imported from unittest.mock
|
||
| import sys | ||
| import os | ||
| import socket | ||
|
|
||
| # Add root to path to import main | ||
| sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||
|
|
||
| import main | ||
Check warningCode scanning / Prospector (reported by Codacy) Cannot import 'main' due to syntax error 'invalid syntax (, line 1286)' (syntax-error) Warning test
Cannot import 'main' due to syntax error 'invalid syntax (, line 1286)' (syntax-error)
Check warningCode scanning / Pylintpython3 (reported by Codacy) Import "import main" should be placed at the top of the module Warning test
Import "import main" should be placed at the top of the module
Check warningCode scanning / Pylint (reported by Codacy) Import "import main" should be placed at the top of the module Warning test
Import "import main" should be placed at the top of the module
|
||
|
|
||
| class TestSSRF(unittest.TestCase): | ||
Check warningCode scanning / Pylintpython3 (reported by Codacy) Missing class docstring Warning test
Missing class docstring
Check warningCode scanning / Pylint (reported by Codacy) Missing class docstring Warning test
Missing class docstring
|
||
| def test_domain_resolving_to_private_ip(self): | ||
| """ | ||
| Test that a domain resolving to a private IP is blocked. | ||
| This simulates a DNS Rebinding attack or SSRF attempt against internal infrastructure. | ||
| """ | ||
| # We need to mock socket.getaddrinfo because the fix will use it. | ||
| # For the current code, this mock is unused, but the test ensures | ||
| # that 'internal.example.com' (which is not an IP literal) passes validation currently | ||
| # and will fail validation (be blocked) after the fix. | ||
|
|
||
| with patch('socket.getaddrinfo') as mock_getaddrinfo: | ||
| # Simulate resolving to 192.168.1.1 | ||
| mock_getaddrinfo.return_value = [ | ||
| (socket.AF_INET, socket.SOCK_STREAM, 6, '', ('192.168.1.1', 443)) | ||
| ] | ||
|
|
||
| url = "https://internal.example.com/config.json" | ||
|
|
||
| # This calls the function in main.py | ||
| result = main.validate_folder_url(url) | ||
|
|
||
| # We expect this to be False (Blocked) | ||
| self.assertFalse(result, "Should block domain resolving to private IP") | ||
|
|
||
| def test_domain_resolving_to_public_ip(self): | ||
| """ | ||
| Test that a domain resolving to a public IP is allowed. | ||
| """ | ||
| with patch('socket.getaddrinfo') as mock_getaddrinfo: | ||
| # Simulate resolving to 8.8.8.8 | ||
| mock_getaddrinfo.return_value = [ | ||
| (socket.AF_INET, socket.SOCK_STREAM, 6, '', ('8.8.8.8', 443)) | ||
| ] | ||
|
|
||
| url = "https://public.example.com/config.json" | ||
|
|
||
| result = main.validate_folder_url(url) | ||
|
|
||
| self.assertTrue(result, "Should allow domain resolving to public IP") | ||
|
|
||
| if __name__ == '__main__': | ||
Check warningCode scanning / Prospector (reported by Codacy) expected 2 blank lines after class or function definition, found 1 (E305) Warning test
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 references to undefined definitions are found. Note