Skip to content

🛡️ Sentinel: [HIGH] Validate rule input to prevent XSS#117

Merged
abhimehro merged 6 commits intomainfrom
sentinel-validate-rules-17576703938918876849
Jan 22, 2026
Merged

🛡️ Sentinel: [HIGH] Validate rule input to prevent XSS#117
abhimehro merged 6 commits intomainfrom
sentinel-validate-rules-17576703938918876849

Conversation

@google-labs-jules
Copy link

Implemented is_valid_rule helper function and integrated it into push_rules to filter out potentially malicious inputs (e.g. <script>) from external blocklists.
Added tests in tests/test_security.py.


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

Validates rule content from external JSON lists to ensure they do not contain malicious characters (XSS payloads, control characters) before pushing to Control D API.
Filters out unsafe rules and logs a warning.

Fixes potential Stored XSS vulnerability via malicious blocklists.
@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 20, 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.

)

# Check what was sent
assert mock_post_form.called

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.
sent_rules.append(v)

# EXPECTED BEHAVIOR: Malicious rules are NOT sent
assert "<script>alert(1)</script>" not in sent_rules

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.

# EXPECTED BEHAVIOR: Malicious rules are NOT sent
assert "<script>alert(1)</script>" not in sent_rules
assert "javascript:void(0)" not in sent_rules # Contains parenthesis/colon?

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.
assert "<script>alert(1)</script>" not in sent_rules
assert "javascript:void(0)" not in sent_rules # Contains parenthesis/colon?
# Wait, 'javascript:void(0)' has '('. My validator blocks '('.
assert "fail' OR '1'='1" not in sent_rules # Contains '

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.
assert "javascript:void(0)" not in sent_rules # Contains parenthesis/colon?
# Wait, 'javascript:void(0)' has '('. My validator blocks '('.
assert "fail' OR '1'='1" not in sent_rules # Contains '
assert "img src=x onerror=alert(1)" not in sent_rules # Contains ( ) or =? No = is allowed?

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.

# Valid rules MUST be sent
assert "valid.com" in sent_rules
assert "safe-domain.com" in sent_rules

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.
# Valid rules MUST be sent
assert "valid.com" in sent_rules
assert "safe-domain.com" in sent_rules
assert "1.1.1.1" in sent_rules

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.
assert "valid.com" in sent_rules
assert "safe-domain.com" in sent_rules
assert "1.1.1.1" in sent_rules
assert "*.wildcard.com" in sent_rules

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 for warnings
# We expect 4 skipped rules
assert mock_log.warning.call_count >= 1

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.
for call in mock_log.warning.call_args_list:
if "Skipping unsafe rule" in str(call):
found_unsafe_log = True
assert found_unsafe_log

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.
**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-14 - [Indirect XSS via Third-Party Data]

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
**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-14 - [Indirect XSS via Third-Party Data]

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

for h in hostnames:
if not is_valid_rule(h):
log.warning(f"Skipping unsafe rule in {sanitize_for_log(folder_name)}: {sanitize_for_log(h)}")

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)

duplicates_count = original_count - len(filtered_hostnames)
if skipped_unsafe > 0:
log.warning(f"Folder {sanitize_for_log(folder_name)}: skipped {skipped_unsafe} unsafe rules")

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,87 @@
import pytest

Check warning

Code scanning / Prospector (reported by Codacy)

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

Unable to import 'pytest' (import-error)
@@ -0,0 +1,87 @@
import pytest

Check warning

Code scanning / Prospector (reported by Codacy)

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

Unable to import 'pytest' (import-error)
mock_post_form = MagicMock()

# Patch the API call
original_post_form = main._api_post_form

Check warning

Code scanning / Prospector (reported by Codacy)

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

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

# Patch the API call
original_post_form = main._api_post_form
main._api_post_form = mock_post_form

Check warning

Code scanning / Prospector (reported by Codacy)

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

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

sent_rules = []
for call in calls:
args, kwargs = call

Check warning

Code scanning / Prospector (reported by Codacy)

Unused variable 'args' (unused-variable) Warning test

Unused variable 'args' (unused-variable)
assert found_unsafe_log

finally:
main._api_post_form = original_post_form

Check warning

Code scanning / Prospector (reported by Codacy)

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

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

# Check what was sent
assert mock_post_form.called

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.
sent_rules.append(v)

# EXPECTED BEHAVIOR: Malicious rules are NOT sent
assert "<script>alert(1)</script>" not in sent_rules

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.

# EXPECTED BEHAVIOR: Malicious rules are NOT sent
assert "<script>alert(1)</script>" not in sent_rules
assert "javascript:void(0)" not in sent_rules # Contains parenthesis/colon?

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 "<script>alert(1)</script>" not in sent_rules
assert "javascript:void(0)" not in sent_rules # Contains parenthesis/colon?
# Wait, 'javascript:void(0)' has '('. My validator blocks '('.
assert "fail' OR '1'='1" not in sent_rules # Contains '

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 "javascript:void(0)" not in sent_rules # Contains parenthesis/colon?
# Wait, 'javascript:void(0)' has '('. My validator blocks '('.
assert "fail' OR '1'='1" not in sent_rules # Contains '
assert "img src=x onerror=alert(1)" not in sent_rules # Contains ( ) or =? No = is allowed?

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.

# Valid rules MUST be sent
assert "valid.com" in sent_rules
assert "safe-domain.com" in sent_rules

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.
# Valid rules MUST be sent
assert "valid.com" in sent_rules
assert "safe-domain.com" in sent_rules
assert "1.1.1.1" in sent_rules

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 "valid.com" in sent_rules
assert "safe-domain.com" in sent_rules
assert "1.1.1.1" in sent_rules
assert "*.wildcard.com" in sent_rules

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 for warnings
# We expect 4 skipped rules
assert mock_log.warning.call_count >= 1

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.
for call in mock_log.warning.call_args_list:
if "Skipping unsafe rule" in str(call):
found_unsafe_log = True
assert found_unsafe_log

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.

for h in hostnames:
if not is_valid_rule(h):
log.warning(f"Skipping unsafe rule in {sanitize_for_log(folder_name)}: {sanitize_for_log(h)}")

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Line too long (106/100) Warning

Line too long (106/100)

duplicates_count = original_count - len(filtered_hostnames)
if skipped_unsafe > 0:
log.warning(f"Folder {sanitize_for_log(folder_name)}: skipped {skipped_unsafe} unsafe rules")

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Line too long (101/100) Warning

Line too long (101/100)
@@ -0,0 +1,87 @@
import pytest

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing module docstring Warning test

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

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

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

standard import "from unittest.mock import MagicMock" should be placed before "import pytest"
for call in calls:
args, kwargs = call
data = kwargs['data']
for k, v in data.items():

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Variable name "v" doesn't conform to snake_case naming style Warning test

Variable name "v" doesn't conform to snake_case naming style
@@ -0,0 +1,87 @@
import pytest

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Unused import pytest Note test

Unused import pytest
mock_post_form = MagicMock()

# Patch the API call
original_post_form = main._api_post_form

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

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

Access to a protected member _api_post_form of a client class

# Patch the API call
original_post_form = main._api_post_form
main._api_post_form = mock_post_form

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

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

Access to a protected member _api_post_form of a client class

sent_rules = []
for call in calls:
args, kwargs = call

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

Unused variable 'args' Note test

Unused variable 'args'
assert found_unsafe_log

finally:
main._api_post_form = original_post_form

Check notice

Code scanning / Pylintpython3 (reported by Codacy)

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

Access to a protected member _api_post_form of a client class

for h in hostnames:
if not is_valid_rule(h):
log.warning(f"Skipping unsafe rule in {sanitize_for_log(folder_name)}: {sanitize_for_log(h)}")

Check warning

Code scanning / Pylint (reported by Codacy)

Line too long (106/100) Warning

Line too long (106/100)

duplicates_count = original_count - len(filtered_hostnames)
if skipped_unsafe > 0:
log.warning(f"Folder {sanitize_for_log(folder_name)}: skipped {skipped_unsafe} unsafe rules")

Check warning

Code scanning / Pylint (reported by Codacy)

Line too long (101/100) Warning

Line too long (101/100)
@@ -0,0 +1,87 @@
import pytest

Check warning

Code scanning / Pylint (reported by Codacy)

Missing module docstring Warning test

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

Check warning

Code scanning / Pylint (reported by Codacy)

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

standard import "from unittest.mock import MagicMock" should be placed before "import pytest"
for call in calls:
args, kwargs = call
data = kwargs['data']
for k, v in data.items():

Check warning

Code scanning / Pylint (reported by Codacy)

Variable name "v" doesn't conform to snake_case naming style Warning test

Variable name "v" doesn't conform to snake_case naming style
@@ -0,0 +1,87 @@
import pytest

Check notice

Code scanning / Pylint (reported by Codacy)

Unused import pytest Note test

Unused import pytest
mock_post_form = MagicMock()

# Patch the API call
original_post_form = main._api_post_form

Check notice

Code scanning / Pylint (reported by Codacy)

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

Access to a protected member _api_post_form of a client class

# Patch the API call
original_post_form = main._api_post_form
main._api_post_form = mock_post_form

Check notice

Code scanning / Pylint (reported by Codacy)

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

Access to a protected member _api_post_form of a client class

sent_rules = []
for call in calls:
args, kwargs = call

Check notice

Code scanning / Pylint (reported by Codacy)

Unused variable 'args' Note test

Unused variable 'args'
assert found_unsafe_log

finally:
main._api_post_form = original_post_form

Check notice

Code scanning / Pylint (reported by Codacy)

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

Access to a protected member _api_post_form of a client class
@abhimehro abhimehro marked this pull request as ready for review January 21, 2026 18:39
Copilot AI review requested due to automatic review settings January 21, 2026 18:39
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 implements XSS validation for rule inputs from external blocklists by adding a new is_valid_rule() helper function and integrating it into the push_rules() function. The implementation filters out potentially malicious inputs (e.g., <script>, javascript:void(0)) from external blocklists before they can be stored in user profiles.

Changes:

  • Added is_valid_rule() validation function to block dangerous characters commonly used in XSS and injection attacks
  • Integrated validation into push_rules() with logging for skipped unsafe rules
  • Added integration test in tests/test_security.py to verify XSS payloads are filtered
  • Documented the vulnerability and prevention strategy in .jules/sentinel.md

Reviewed changes

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

File Description
main.py Added is_valid_rule() function to validate rule safety and integrated it into push_rules() to filter out malicious inputs before API submission
tests/test_security.py Added integration test to verify that XSS payloads are filtered while legitimate domain rules are allowed through
.jules/sentinel.md Documented the indirect XSS vulnerability via third-party data and prevention measures

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

Comment on lines +5 to +87
def test_push_rules_filters_xss_payloads():
"""
Verify that push_rules filters out malicious strings (XSS payloads).
"""
mock_client = MagicMock()
mock_post_form = MagicMock()

# Patch the API call
original_post_form = main._api_post_form
main._api_post_form = mock_post_form

# Patch the logger to verify warnings
mock_log = MagicMock()
original_log = main.log
main.log = mock_log

try:
malicious_rules = [
"<script>alert(1)</script>",
"valid.com",
"javascript:void(0)",
"fail' OR '1'='1",
"img src=x onerror=alert(1)",
"safe-domain.com",
"1.1.1.1",
"*.wildcard.com"
]

main.push_rules(
profile_id="p1",
folder_name="f1",
folder_id="fid1",
do=1,
status=1,
hostnames=malicious_rules,
existing_rules=set(),
client=mock_client
)

# Check what was sent
assert mock_post_form.called
calls = mock_post_form.call_args_list

sent_rules = []
for call in calls:
args, kwargs = call
data = kwargs['data']
for k, v in data.items():
if k.startswith("hostnames["):
sent_rules.append(v)

# EXPECTED BEHAVIOR: Malicious rules are NOT sent
assert "<script>alert(1)</script>" not in sent_rules
assert "javascript:void(0)" not in sent_rules # Contains parenthesis/colon?
# Wait, 'javascript:void(0)' has '('. My validator blocks '('.
assert "fail' OR '1'='1" not in sent_rules # Contains '
assert "img src=x onerror=alert(1)" not in sent_rules # Contains ( ) or =? No = is allowed?
# "img src=x onerror=alert(1)" contains spaces?
# My validator: isprintable() is True.
# dangerous_chars: set("<>\"'`();{}[]")
# <script> has < >
# javascript:void(0) has ( )
# fail' has '
# img src=x ... has ( )

# Valid rules MUST be sent
assert "valid.com" in sent_rules
assert "safe-domain.com" in sent_rules
assert "1.1.1.1" in sent_rules
assert "*.wildcard.com" in sent_rules

# Check logs for warnings
# We expect 4 skipped rules
assert mock_log.warning.call_count >= 1
found_unsafe_log = False
for call in mock_log.warning.call_args_list:
if "Skipping unsafe rule" in str(call):
found_unsafe_log = True
assert found_unsafe_log

finally:
main._api_post_form = original_post_form
main.log = original_log
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

The test file uses a plain function with manual mocking rather than following the unittest.TestCase pattern used consistently in other test files (test_ssrf.py, test_ssrf_enhanced.py, test_ux.py). This inconsistency makes the test suite harder to maintain and run. Consider refactoring to use unittest.TestCase with proper setUp/tearDown methods for consistent test structure.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +87
import pytest
from unittest.mock import MagicMock
import main

def test_push_rules_filters_xss_payloads():
"""
Verify that push_rules filters out malicious strings (XSS payloads).
"""
mock_client = MagicMock()
mock_post_form = MagicMock()

# Patch the API call
original_post_form = main._api_post_form
main._api_post_form = mock_post_form

# Patch the logger to verify warnings
mock_log = MagicMock()
original_log = main.log
main.log = mock_log

try:
malicious_rules = [
"<script>alert(1)</script>",
"valid.com",
"javascript:void(0)",
"fail' OR '1'='1",
"img src=x onerror=alert(1)",
"safe-domain.com",
"1.1.1.1",
"*.wildcard.com"
]

main.push_rules(
profile_id="p1",
folder_name="f1",
folder_id="fid1",
do=1,
status=1,
hostnames=malicious_rules,
existing_rules=set(),
client=mock_client
)

# Check what was sent
assert mock_post_form.called
calls = mock_post_form.call_args_list

sent_rules = []
for call in calls:
args, kwargs = call
data = kwargs['data']
for k, v in data.items():
if k.startswith("hostnames["):
sent_rules.append(v)

# EXPECTED BEHAVIOR: Malicious rules are NOT sent
assert "<script>alert(1)</script>" not in sent_rules
assert "javascript:void(0)" not in sent_rules # Contains parenthesis/colon?
# Wait, 'javascript:void(0)' has '('. My validator blocks '('.
assert "fail' OR '1'='1" not in sent_rules # Contains '
assert "img src=x onerror=alert(1)" not in sent_rules # Contains ( ) or =? No = is allowed?
# "img src=x onerror=alert(1)" contains spaces?
# My validator: isprintable() is True.
# dangerous_chars: set("<>\"'`();{}[]")
# <script> has < >
# javascript:void(0) has ( )
# fail' has '
# img src=x ... has ( )

# Valid rules MUST be sent
assert "valid.com" in sent_rules
assert "safe-domain.com" in sent_rules
assert "1.1.1.1" in sent_rules
assert "*.wildcard.com" in sent_rules

# Check logs for warnings
# We expect 4 skipped rules
assert mock_log.warning.call_count >= 1
found_unsafe_log = False
for call in mock_log.warning.call_args_list:
if "Skipping unsafe rule" in str(call):
found_unsafe_log = True
assert found_unsafe_log

finally:
main._api_post_form = original_post_form
main.log = original_log
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

There is no direct unit test for the is_valid_rule function itself. While the integration test checks the behavior through push_rules, adding dedicated unit tests for is_valid_rule would improve test coverage and make it easier to verify edge cases like empty strings, non-printable characters, and each dangerous character individually.

Copilot uses AI. Check for mistakes.
…ng sanitization

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
abhimehro and others added 3 commits January 21, 2026 13:08
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
Copy link
Owner

Hi @google-lab-jules, please open a new pull request to apply any remaining changes based on the comments in this thread. Thanks!

@google-labs-jules
Copy link
Author

Hi @google-lab-jules, please open a new pull request to apply any remaining changes based on the comments in this thread. Thanks!

Acknowledged. I have implemented the security fix for validating rules to prevent XSS and have submitted the changes in the sentinel-validate-rules branch.

Validates rule content from external JSON lists to ensure they do not contain malicious characters (XSS payloads, control characters) before pushing to Control D API.
Filters out unsafe rules and logs a warning.

Fixes potential Stored XSS vulnerability via malicious blocklists.
@abhimehro abhimehro merged commit a03a75d into main Jan 22, 2026
17 of 18 checks passed
@abhimehro abhimehro deleted the sentinel-validate-rules-17576703938918876849 branch January 22, 2026 11:14
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