Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## 2024-05-18 - [Path Traversal in Manual Path Resolution]
**Vulnerability:** In `resolve_module_path`, manual path normalization for unresolved paths incorrectly popped `std::path::Component::ParentDir` from the components list regardless of the previous component. This could pop `RootDir` or `Prefix` components, leading to potential path traversal vulnerabilities or generating entirely wrong absolute paths when given multiple `..` segments.
**Learning:** `std::path::Component` does not inherently block you from popping structural elements like `RootDir`. When manually normalizing paths by collecting components, you must handle `..` explicitly by checking the last element before popping.
**Prevention:** Always verify the type of the last component before popping it for a `ParentDir`. Explicitly ignore `ParentDir` if the last component is `RootDir` or `Prefix`, and push it if the list is empty or the last component is also `ParentDir`.
10 changes: 9 additions & 1 deletion crates/flow/src/incremental/extractors/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,15 @@ impl TypeScriptDependencyExtractor {
for component in resolved.components() {
match component {
std::path::Component::ParentDir => {
components.pop();
if let Some(last) = components.last() {
match last {
std::path::Component::RootDir | std::path::Component::Prefix(_) => {}
std::path::Component::ParentDir => components.push(component),
_ => { components.pop(); }
}
} else {
components.push(component);
}
}
std::path::Component::CurDir => {}
_ => components.push(component),
Expand Down