🛡️ Sentinel: [MEDIUM] Fix regex newline injection and broken exclusion logic#113
🛡️ Sentinel: [MEDIUM] Fix regex newline injection and broken exclusion logic#113calionauta wants to merge 1 commit into
Conversation
- Replaced vulnerable `$` anchor with `\Z` in `_is_valid_skill_name` within both `local_source.py` and `external_source.py` to prevent newline injection. - Refactored `_ignore_func` in `git_publish.py` to use `fnmatch.filter`, ensuring that patterns like `sessions` and `cache` are correctly ignored during publication. - Added regression test `tests/test_skill_validation_sentinel.py`. Co-authored-by: renatocaliari <1719651+renatocaliari@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. |
There was a problem hiding this comment.
Code Review
This pull request improves skill name validation in both external_source.py and local_source.py by using \Z in the regular expression to prevent newline injection, and adds corresponding unit tests. It also refactors the file ignoring logic in git_publish.py to use fnmatch.filter. The reviewer suggested simplifying the file ignoring logic further by directly leveraging shutil.ignore_patterns from the standard library.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| import fnmatch | ||
|
|
||
| def _ignore(path, names): | ||
| ignored = [] | ||
| for name in names: | ||
| for pattern in patterns: | ||
| if pattern.startswith('*.'): | ||
| if name.endswith(pattern[1:]): | ||
| ignored.append(name) | ||
| break | ||
| elif pattern.startswith('.'): | ||
| if name == pattern or name.startswith(pattern.rstrip('/') + '/'): | ||
| ignored.append(name) | ||
| break | ||
| return ignored | ||
| for pattern in patterns: | ||
| ignored.extend(fnmatch.filter(names, pattern)) | ||
| return set(ignored) | ||
|
|
||
| return _ignore |
There was a problem hiding this comment.
Instead of manually implementing the pattern filtering logic using fnmatch.filter and returning a custom callable, you can directly leverage the standard library's shutil.ignore_patterns function. This simplifies the code, improves maintainability, and avoids redundant implementation of standard library features.
| import fnmatch | |
| def _ignore(path, names): | |
| ignored = [] | |
| for name in names: | |
| for pattern in patterns: | |
| if pattern.startswith('*.'): | |
| if name.endswith(pattern[1:]): | |
| ignored.append(name) | |
| break | |
| elif pattern.startswith('.'): | |
| if name == pattern or name.startswith(pattern.rstrip('/') + '/'): | |
| ignored.append(name) | |
| break | |
| return ignored | |
| for pattern in patterns: | |
| ignored.extend(fnmatch.filter(names, pattern)) | |
| return set(ignored) | |
| return _ignore | |
| return shutil.ignore_patterns(*patterns) |
🚨 Severity: MEDIUM
💡 Vulnerability:
_is_valid_skill_namefunctions used the$anchor, which in Python'sremodule matches before a trailing newline. This could allow injecting newlines into skill names, potentially leading to argument injection if used in shell commands later._ignore_funcinsrc/agent_sync/publish/git_publish.pyhad a manual matching logic that only handled patterns starting with*.or., failing to filter out simple directory names likesessionsorcachelisted inDEFAULT_IGNORE_PATTERNS.🎯 Impact:
🔧 Fix:
\Zfor absolute end-of-string matching._ignore_functo usefnmatch.filterfor standard and robust pattern matching againstDEFAULT_IGNORE_PATTERNS.✅ Verification:
tests/test_skill_validation_sentinel.pyto verify that trailing newlines are now rejected.sessionsandcachedirectories are now correctly ignored byshutil.copytreeduring the publish flow.PR created automatically by Jules for task 13976260757112085987 started by @renatocaliari