🛡️ Sentinel: [CRITICAL/HIGH] Fix path traversal in manual path normalization#240
🛡️ Sentinel: [CRITICAL/HIGH] Fix path traversal in manual path normalization#240bashandbone wants to merge 1 commit into
Conversation
…zation Implemented safe path normalization during unresolved module resolution in `crates/flow/src/incremental/extractors/typescript.rs` to correctly handle `std::path::Component::ParentDir`. Prevented popping `RootDir` or `Prefix`, protecting against converting absolute paths to relative paths or unauthorized directory traversal. Added security journal entry detailing the manual normalization vulnerability in `.jules/sentinel.md`. 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 GuideAdjusts manual path normalization in the TypeScript dependency extractor to safely handle ParentDir components and prevent path traversal, and records the security fix and guidance in Sentinel documentation. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Pull request overview
This PR addresses a high-severity path traversal risk in the TypeScript incremental dependency extractor by hardening the manual path normalization fallback used when canonicalize() fails.
Changes:
- Hardened manual
../handling to avoid poppingRootDir/Prefixand to preserve contiguousParentDirsequences safely. - Added a Sentinel security log entry documenting the vulnerability, learning, and prevention guidance.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
crates/flow/src/incremental/extractors/typescript.rs |
Fixes manual path normalization logic to prevent unsafe component popping during unresolved module resolution. |
.jules/sentinel.md |
Adds Sentinel entry documenting the vulnerability and prevention guidance. |
Comments suppressed due to low confidence (1)
crates/flow/src/incremental/extractors/typescript.rs:829
- The updated manual
ParentDirnormalization fixes subtle boundary cases, but there are no unit tests covering the newly-handled scenarios (e.g., more..segments than availableNormalcomponents so..must be preserved, and ensuringRootDir/Prefixare never removed). Please add regression tests aroundresolve_module_pathfor these edge cases so this security fix doesn’t regress.
// If canonicalize fails (file doesn't exist), manually resolve
let mut components = Vec::new();
for component in resolved.components() {
match component {
std::path::Component::ParentDir => {
if let Some(c) = components.last() {
if c == &std::path::Component::ParentDir {
components.push(component);
} else if !matches!(
c,
std::path::Component::RootDir | std::path::Component::Prefix(_)
) {
components.pop();
}
} else {
components.push(component);
}
}
std::path::Component::CurDir => {}
_ => components.push(component),
}
}
resolved = components.iter().collect();
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ## 2025-02-27 - [Path Traversal via Manual Path Normalization] | ||
| **Vulnerability:** In `crates/flow/src/incremental/extractors/typescript.rs`, manual path normalization for unresolved module paths naively popped components from the path stack when encountering `ParentDir` (`../`). This allowed popping the `RootDir` or `Prefix`, converting an absolute path into a relative one, or misinterpreting repeated `../` sequences, leading to potential path traversal vulnerabilities. | ||
| **Learning:** `std::path::Component::ParentDir` resolution in Rust requires careful state management. Simply using `components.pop()` fails to account for boundary conditions (like `RootDir` or empty stacks) which are crucial for maintaining the secure scope of file resolutions. | ||
| **Prevention:** Always use the robust component popping pattern: When encountering `ParentDir`, check if the last component in the stack is also `ParentDir`. If it is, or if the stack is empty, push `ParentDir`. Only pop the stack if the last component is a `Normal` directory, and never pop `RootDir` or `Prefix`. |
🚨 Severity: HIGH
💡 Vulnerability: When a path could not be resolved using standard canonicalization (e.g., an unresolved module import), the manual path resolution logic naively handled
../by popping the last element from an intermediate stack. This meantcomponents.pop()could inadvertently remove a root directory (/) or a volume prefix, effectively turning absolute file paths into relative ones, or failing to preserve valid relative paths (../../a). This opened the door for potential Path Traversal vulnerabilities during module extractions.🎯 Impact: An attacker or misconfigured malicious file could potentially exploit
../strings to bypass directory boundaries or access files outside the expected context during analysis.🔧 Fix: Adjusted the manual normalization loop to ensure
ParentDirsafely collapsesNormalcomponents. It explicitly blocks poppingRootDirandPrefix, and handles contiguousParentDirstack sequences safely.✅ Verification:
cargo clippy --workspace -- -D warnings.cargo test -p thread-flow --test extractor_typescript_tests.PR created automatically by Jules for task 5611789745888416068 started by @bashandbone
Summary by Sourcery
Harden manual path normalization in the TypeScript dependency extractor to prevent unsafe parent directory handling and document the resolved vulnerability in Sentinel logs.
Bug Fixes:
ParentDir, avoiding potential path traversal and incorrect absolute-to-relative path conversions.Documentation:
ParentDirhandling pattern.