🛡️ Sentinel: [CRITICAL] Fix path traversal in TypeScript module resolution#266
Conversation
…ution Fixes a critical path traversal vulnerability in `crates/flow/src/incremental/extractors/typescript.rs` where manual path normalization blindly popped directory components when resolving `..`. This allowed traversal paths like `/..` to strip the root directory (`/`), or escaping above the starting boundary when traversing upwards via `../../`. The fix correctly checks the last component in the stack, preventing the popping of `RootDir` and `Prefix`, and correctly pushing `ParentDir` when the stack is empty or already at `ParentDir`. 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 guide (collapsed on small PRs)Reviewer's GuideFixes a critical path traversal vulnerability in the TypeScript module resolver’s manual path normalization fallback by making ParentDir handling root/prefix-safe and documenting the vulnerability pattern in Sentinel notes. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The nested
if let+matchinside theParentDirarm is getting a bit dense; consider extracting this logic into a small helper function (e.g.,fn handle_parent_dir(components: &mut Vec<Component>)) to make the control flow and invariants clearer and easier to validate. - In the
ParentDirhandling, the behavior for Windows-specificComponent::Prefixand related path forms is subtle; it may be worth explicitly documenting (in code comments) the intended semantics for UNC/prefixed paths so future changes don’t inadvertently reintroduce traversal issues on non-Unix platforms.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The nested `if let` + `match` inside the `ParentDir` arm is getting a bit dense; consider extracting this logic into a small helper function (e.g., `fn handle_parent_dir(components: &mut Vec<Component>)`) to make the control flow and invariants clearer and easier to validate.
- In the `ParentDir` handling, the behavior for Windows-specific `Component::Prefix` and related path forms is subtle; it may be worth explicitly documenting (in code comments) the intended semantics for UNC/prefixed paths so future changes don’t inadvertently reintroduce traversal issues on non-Unix platforms.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 the TypeScript dependency extractor’s manual path normalization fallback to prevent path traversal issues when canonicalize() fails, and adds a Sentinel learning entry documenting the vulnerability pattern.
Changes:
- Updated
Component::ParentDirhandling inresolve_module_pathto avoid poppingRootDir/Prefixand to preserve leading..for relative paths. - Added a
.jules/sentinel.mdentry documenting the manual path normalization pitfall and prevention guidance.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| crates/flow/src/incremental/extractors/typescript.rs | Hardens manual .. normalization to prevent root/prefix popping and preserve relative parent traversals. |
| .jules/sentinel.md | Documents the vulnerability pattern and recommended prevention approach. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ## 2024-05-24 - [Path Traversal Vulnerability in Manual Path Resolution] | ||
| **Vulnerability:** Path traversal vulnerability during manual path normalization. |
| std::path::Component::ParentDir => { | ||
| components.pop(); | ||
| if let Some(last) = components.last() { | ||
| match last { | ||
| std::path::Component::RootDir | std::path::Component::Prefix(_) => { | ||
| // Path traversal block: do not pop root or prefix | ||
| } | ||
| std::path::Component::ParentDir => { | ||
| components.push(component); | ||
| } | ||
| _ => { | ||
| components.pop(); | ||
| } | ||
| } | ||
| } else { | ||
| components.push(component); | ||
| } |
🚨 Severity: CRITICAL
💡 Vulnerability: A path traversal vulnerability existed in
crates/flow/src/incremental/extractors/typescript.rswithin theresolve_modulemanual path normalization fallback. Whenstd::fs::canonicalizefails (e.g., if the file doesn't exist yet), the code manually resolves..components by blindly popping from a stack of components. This permitted escaping absolute bounds (poppingRootDir) and corrupted relative parent traversals (e.g., dropping../components entirely rather than preserving them).🎯 Impact: An attacker or malformed module specifier could traverse outside the intended extraction boundaries, resolving or referencing files inappropriately.
🔧 Fix: Updated the
Component::ParentDirmatch arm to safely inspect the last item on the component stack. It explicitly prevents poppingRootDirandPrefixcomponents, and it preserves..components when climbing out of a relative directory by pushingParentDironto the stack if it's empty or already ends inParentDir. Added an inline comment documenting the path traversal block.✅ Verification:
cargo test -p thread-flow --test extractor_typescript_testswhich verifies module resolutions are correct..jules/sentinel.mddetailing the vulnerability pattern to prevent similar occurrences.PR created automatically by Jules for task 15949326259489310145 started by @bashandbone
Summary by Sourcery
Fix unsafe manual path normalization in TypeScript module resolution and document the vulnerability pattern for future prevention.
Bug Fixes:
Documentation: