🛡️ Sentinel: [CRITICAL] Fix arbitrary code execution in AST eval via unrestricted ast.Call#380
Conversation
…unrestricted ast.Call * Discovered that the dynamic type evaluation in `Container._safe_eval_type` using safe AST traversal permitted arbitrary `ast.Call` nodes. * This created an Arbitrary Code Execution (ACE) vulnerability, allowing attackers to execute any callable function present in the module's global namespace via unvalidated string inputs. * Implemented strict whitelisting within `TypeValidator.generic_visit` to explicitly block any `ast.Call` nodes unless the function name matches an approved set of safe, required functions (e.g., `Depends`, `depends`, `Field`, `Parameter`). * Added an inline comment documenting the security concern and updated the `.jules/sentinel.md` journal with critical learnings. * Ran formatting, linting, targeted tests, and the full test suite to ensure the fix is secure and introduces no regressions. Co-authored-by: bashandbone <89049923+bashandbone@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. |
Reviewer's GuideTightens the safe AST-based type evaluation in the DI container by whitelisting allowable function calls in type strings and documents the new security mitigation in the Sentinel notes. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
🤖 Hi @bashandbone, I've received your request, and I'm working on it now! You can track my progress in the logs for more details. |
|
🤖 I'm sorry @bashandbone, but I was unable to process your request. Please see the logs for more details. |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The
allowed_funcsset is recreated on everyast.Callvisit; consider hoisting it to an outer constant or class attribute to avoid repeated allocation and keep the whitelist centralized. - When
func_namecannot be resolved (staysNone), the error message currently includesNone; consider using a more generic message or explicitly distinguishing unresolved call targets for clearer debugging.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `allowed_funcs` set is recreated on every `ast.Call` visit; consider hoisting it to an outer constant or class attribute to avoid repeated allocation and keep the whitelist centralized.
- When `func_name` cannot be resolved (stays `None`), the error message currently includes `None`; consider using a more generic message or explicitly distinguishing unresolved call targets for clearer debugging.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
This PR hardens Container._safe_eval_type (used to resolve string-based type annotations in the DI container) to reduce the risk of arbitrary code execution by restricting which ast.Call nodes are permitted during AST-validated eval.
Changes:
- Add an
ast.Callwhitelist in the AST validator used by_safe_eval_type. - Suppress cyclomatic complexity warning for
_safe_eval_typevia# noqa: C901. - Document the new Sentinel finding in
.jules/sentinel.md.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/codeweaver/core/di/container.py |
Restricts which call expressions are allowed when evaluating string type hints via AST validation. |
.jules/sentinel.md |
Documents the AST-eval call restriction as a Sentinel security entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| self._providers_loaded: bool = False # Track if auto-discovery has run | ||
|
|
||
| def _safe_eval_type(self, type_str: str, globalns: dict[str, Any]) -> Any | None: | ||
| def _safe_eval_type(self, type_str: str, globalns: dict[str, Any]) -> Any | None: # noqa: C901 |
| if isinstance(node, ast.Call): | ||
| allowed_funcs = {"Depends", "depends", "Field", "PrivateAttr", "Tag", "Parameter"} | ||
| func_name = None | ||
| if isinstance(node.func, ast.Name): | ||
| func_name = node.func.id | ||
| elif isinstance(node.func, ast.Attribute): | ||
| func_name = node.func.attr | ||
|
|
||
| if func_name not in allowed_funcs: | ||
| raise TypeError(f"Forbidden function call in type string: {func_name}") |
🚨 Severity: CRITICAL
💡 Vulnerability: Discovered that the dynamic type evaluation in
Container._safe_eval_typeusing safe AST traversal permitted arbitraryast.Callnodes.🎯 Impact: This allowed for Arbitrary Code Execution (ACE) via the module's global namespace if unvalidated strings were processed, circumventing standard Python
evalrestrictions.🔧 Fix: Implemented strict whitelisting to explicitly reject
ast.Callnodes unless the function being called is one of the strictly recognized list (Depends,depends,Field,PrivateAttr,Tag,Parameter).✅ Verification: Successfully ran
mise //:test tests/unit/core/diandmise //:testlocally to verify functionality and ensure no regressions. Also passed full repository linting and formatting.PR created automatically by Jules for task 15109523051562673142 started by @bashandbone
Summary by Sourcery
Harden safe type evaluation in the DI container to prevent arbitrary code execution via unsafe AST calls and document the new Sentinel finding.
Bug Fixes:
Documentation: