π‘οΈ Sentinel: Fix broken validation and add length limits#425
π‘οΈ Sentinel: Fix broken validation and add length limits#425
Conversation
- Fixed syntax error in `validate_folder_data` that prevented execution. - Added input length limits to prevent DoS: - Folder IDs: max 64 chars - Folder Names: max 64 chars - Rules: max 255 chars - Updated `push_rules` to enforce rule length limit (previously bypassed standard validation). - Added tests in `tests/test_security_limits.py`. Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com>
|
π 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
|
|
π Development Partner is reviewing this PR. Will provide feedback shortly. |
Summary of ChangesHello @abhimehro, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses critical security vulnerabilities by fixing a broken validation function and implementing comprehensive length limits across various input fields. The changes enhance application stability, prevent potential Denial of Service attacks, and ensure that security controls are consistently applied, even in optimized code paths. The introduction of new tests verifies the effectiveness of these security improvements. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with π and π on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
|
||
| def test_is_valid_folder_name_limits(): | ||
| # Test length limit: 64 characters (pass) | ||
| assert main.is_valid_folder_name("a" * 64) is True |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| assert main.is_valid_folder_name("a" * 64) is True | ||
|
|
||
| # Test length limit: 65 characters (fail) | ||
| assert main.is_valid_folder_name("a" * 65) is False |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| def test_is_valid_rule_limits(): | ||
| # Test length limit: 255 characters (pass) | ||
| # Using 'a' which matches the regex ^[a-zA-Z0-9.\-_:*/@]+$ | ||
| assert main.is_valid_rule("a" * 255) is True |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| assert main.is_valid_rule("a" * 255) is True | ||
|
|
||
| # Test length limit: 256 characters (fail) | ||
| assert main.is_valid_rule("a" * 256) is False |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| def test_validate_folder_id_limits(): | ||
| # Test length limit: 64 characters (pass) | ||
| # Using 'a' which matches ^[a-zA-Z0-9_.-]+$ | ||
| assert main.validate_folder_id("a" * 64) is True |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
|
|
||
| # Test length limit: 65 characters (fail) | ||
| # We pass log_errors=False to avoid cluttering output | ||
| assert main.validate_folder_id("a" * 65, log_errors=False) is False |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| return False | ||
| if len(folder_id) > 64: | ||
| if log_errors: | ||
| log.error(f"Invalid folder ID length (max 64): {len(folder_id)}") |
Check warning
Code scanning / Prospector (reported by Codacy)
Use lazy % formatting in logging functions (logging-fstring-interpolation) Warning
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
Check warning
Code scanning / Prospector (reported by Codacy)
Unable to import 'pytest' (import-error) Warning test
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
Check warning
Code scanning / Prospector (reported by Codacy)
Unused import pytest (unused-import) Warning test
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
| from unittest.mock import MagicMock, patch | |||
Check warning
Code scanning / Prospector (reported by Codacy)
Unused MagicMock imported from unittest.mock (unused-import) Warning test
main.py
Outdated
Check warning
Code scanning / Pylint (reported by Codacy)
Line too long (120/100) Warning
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
Check warning
Code scanning / Pylint (reported by Codacy)
Missing module docstring Warning test
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
| from unittest.mock import MagicMock, patch | |||
Check warning
Code scanning / Pylint (reported by Codacy)
standard import "from unittest.mock import MagicMock, patch" should be placed before "import pytest" Warning test
| from unittest.mock import MagicMock, patch | ||
| import main | ||
|
|
||
| def test_is_valid_folder_name_limits(): |
Check warning
Code scanning / Pylint (reported by Codacy)
Missing function docstring Warning test
| # Test length limit: 65 characters (fail) | ||
| assert main.is_valid_folder_name("a" * 65) is False | ||
|
|
||
| def test_is_valid_rule_limits(): |
Check warning
Code scanning / Pylint (reported by Codacy)
Missing function docstring Warning test
| # Test length limit: 256 characters (fail) | ||
| assert main.is_valid_rule("a" * 256) is False | ||
|
|
||
| def test_validate_folder_id_limits(): |
Check warning
Code scanning / Pylint (reported by Codacy)
Missing function docstring Warning test
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
Check notice
Code scanning / Pylint (reported by Codacy)
Unused import pytest Note test
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
| from unittest.mock import MagicMock, patch | |||
Check notice
Code scanning / Pylint (reported by Codacy)
Unused MagicMock imported from unittest.mock Note test
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
| from unittest.mock import MagicMock, patch | |||
Check notice
Code scanning / Pylint (reported by Codacy)
Unused patch imported from unittest.mock Note test
|
|
||
| def test_is_valid_folder_name_limits(): | ||
| # Test length limit: 64 characters (pass) | ||
| assert main.is_valid_folder_name("a" * 64) is True |
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
| assert main.is_valid_folder_name("a" * 64) is True | ||
|
|
||
| # Test length limit: 65 characters (fail) | ||
| assert main.is_valid_folder_name("a" * 65) is False |
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
| def test_is_valid_rule_limits(): | ||
| # Test length limit: 255 characters (pass) | ||
| # Using 'a' which matches the regex ^[a-zA-Z0-9.\-_:*/@]+$ | ||
| assert main.is_valid_rule("a" * 255) is True |
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
| assert main.is_valid_rule("a" * 255) is True | ||
|
|
||
| # Test length limit: 256 characters (fail) | ||
| assert main.is_valid_rule("a" * 256) is False |
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
| def test_validate_folder_id_limits(): | ||
| # Test length limit: 64 characters (pass) | ||
| # Using 'a' which matches ^[a-zA-Z0-9_.-]+$ | ||
| assert main.validate_folder_id("a" * 64) is True |
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
|
|
||
| # Test length limit: 65 characters (fail) | ||
| # We pass log_errors=False to avoid cluttering output | ||
| assert main.validate_folder_id("a" * 65, log_errors=False) is False |
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
main.py
Outdated
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Line too long (120/100) Warning
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Missing module docstring Warning test
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
| from unittest.mock import MagicMock, patch | |||
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
standard import "from unittest.mock import MagicMock, patch" should be placed before "import pytest" Warning test
| from unittest.mock import MagicMock, patch | ||
| import main | ||
|
|
||
| def test_is_valid_folder_name_limits(): |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Missing function or method docstring Warning test
| # Test length limit: 65 characters (fail) | ||
| assert main.is_valid_folder_name("a" * 65) is False | ||
|
|
||
| def test_is_valid_rule_limits(): |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Missing function or method docstring Warning test
| # Test length limit: 256 characters (fail) | ||
| assert main.is_valid_rule("a" * 256) is False | ||
|
|
||
| def test_validate_folder_id_limits(): |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Missing function or method docstring Warning test
| return False | ||
| if len(folder_id) > 64: | ||
| if log_errors: | ||
| log.error(f"Invalid folder ID length (max 64): {len(folder_id)}") |
Check notice
Code scanning / Pylintpython3 (reported by Codacy)
Use lazy % formatting in logging functions Note
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
Check notice
Code scanning / Pylintpython3 (reported by Codacy)
Unused import pytest Note test
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
| from unittest.mock import MagicMock, patch | |||
Check notice
Code scanning / Pylintpython3 (reported by Codacy)
Unused MagicMock imported from unittest.mock Note test
| @@ -0,0 +1,27 @@ | |||
| import pytest | |||
| from unittest.mock import MagicMock, patch | |||
Check notice
Code scanning / Pylintpython3 (reported by Codacy)
Unused patch imported from unittest.mock Note test
There was a problem hiding this comment.
Pull request overview
This PR addresses validation-related security and stability issues by repairing validate_folder_data syntax/logic, adding input length limits to reduce DoS risk, and extending test coverage to enforce these limits.
Changes:
- Add max-length constraints for folder IDs/names (64) and rules (255) in validation helpers.
- Fix broken
validate_folder_datalogic and ensure it returnsTrueon success. - Add a new security-focused test module covering the new length limits.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
main.py |
Adds length limits to validators, fixes validate_folder_data, and updates push_rules filtering logic. |
tests/test_security_limits.py |
Introduces tests that assert folder/rule length constraints are enforced. |
.jules/sentinel.md |
Documents the optimization/validation drift risk as a Sentinel entry. |
| import pytest | ||
| from unittest.mock import MagicMock, patch |
There was a problem hiding this comment.
pytest, MagicMock, and patch are imported but not used in this test module. Removing unused imports will keep the test file minimal and avoid implying mocks/fixtures are required here.
| import pytest | |
| from unittest.mock import MagicMock, patch |
| # Optimization 2: Inline regex match and check existence | ||
| # Using a local reference to the match method avoids function call overhead | ||
| # in the hot loop. This provides a measurable speedup for large lists. | ||
| match_rule = RULE_PATTERN.match | ||
|
|
||
| for h in unique_hostnames: | ||
| if h in existing_rules: | ||
| continue | ||
|
|
||
| if not match_rule(h): | ||
| # Enforce max length (255) and regex pattern | ||
| if len(h) > 255 or not match_rule(h): |
There was a problem hiding this comment.
push_rules still duplicates the canonical rule-validation logic (length + RULE_PATTERN.match) instead of reusing is_valid_rule. This can drift again if is_valid_rule gains additional checks; consider calling is_valid_rule(h) (optionally via a local alias for performance) and/or centralizing the max-length value in a shared constant used by both paths.
There was a problem hiding this comment.
Code Review
This pull request effectively addresses several security vulnerabilities by fixing broken validation logic in validate_folder_data and introducing much-needed length limits for various inputs to prevent potential Denial of Service attacks. The changes are well-documented and include new tests to verify the added constraints. My feedback focuses on improving the long-term maintainability of these new security limits by suggesting the use of named constants instead of hardcoded 'magic numbers', which will make the code safer and easier to manage.
| """Validates folder ID (PK) format to prevent path traversal.""" | ||
| if not folder_id: | ||
| return False | ||
| if len(folder_id) > 64: |
There was a problem hiding this comment.
The value 64 is used as a maximum length for folder IDs here, and also for folder names (is_valid_folder_name) and profile IDs (is_valid_profile_id_format). To improve maintainability and ensure these security-related limits are consistent, consider defining a module-level constant (e.g., MAX_ID_LENGTH = 64) and using it in all relevant validation functions.
| return False | ||
|
|
||
| # Enforce max length to prevent DoS | ||
| if len(rule) > 255: |
There was a problem hiding this comment.
The maximum rule length 255 is hardcoded here and also in push_rules. To prevent potential drift between this canonical validation function and the inlined performance optimization (as noted in .jules/sentinel.md), it's best to define this value as a module-level constant (e.g., MAX_RULE_LENGTH = 255) and use it in both places. This will make the code safer and easier to maintain.
| return False | ||
|
|
||
| # Enforce max length to prevent DoS (matching profile ID limit) | ||
| if len(name) > 64: |
There was a problem hiding this comment.
|
|
||
| if not match_rule(h): | ||
| # Enforce max length (255) and regex pattern | ||
| if len(h) > 255 or not match_rule(h): |
There was a problem hiding this comment.
The maximum rule length 255 is hardcoded here, duplicating the value from is_valid_rule. To prevent potential logic drift between this optimized path and the canonical validation function (a risk highlighted in .jules/sentinel.md), it would be safer to use a shared module-level constant (e.g., MAX_RULE_LENGTH = 255) in both places.
Understood. Acknowledging that this work is superseded by #412 and stopping work on this task. |
π¨ Severity: HIGH
π‘ Vulnerability:
validate_folder_datacontained invalid syntax, causing the application to crash or fail validation silently (Availability).push_rulesoptimization bypassed the standardis_valid_rulecheck.π― Impact:
π§ Fix:
validate_folder_dataand restored proper validation logic.push_rulesto respect the new length limit inline.β Verification:
tests/test_security_limits.pyto verify length constraints.PR created automatically by Jules for task 11441188995627958754 started by @abhimehro