Skip to content

Fix preopen path traversal in WASI 0.2 descriptor.open-at - #466

Draft
Luca388 wants to merge 1 commit into
Samsung:mainfrom
Luca388:issue-458-repro
Draft

Fix preopen path traversal in WASI 0.2 descriptor.open-at#466
Luca388 wants to merge 1 commit into
Samsung:mainfrom
Luca388:issue-458-repro

Conversation

@Luca388

@Luca388 Luca388 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Fixes a path traversal issue in WASI 0.2 descriptor.open-at.

Fix

Prevents .. and symbolic links from escaping the preopen boundary.

Note

The Unix implementation uses openat() and readlinkat() and is still being completed.

Windows support will be implemented separately.

Progress

Completed

  • Reject absolute paths and prevent .. from escaping the preopen root
  • Traverse path components relative to directory file descriptors with openat()
  • Resolve relative symbolic links safely with readlinkat()
  • Reject absolute symbolic-link targets and prevent multi-level symlink escapes
  • Limit symbolic-link resolution depth
  • Clean up opened file descriptors on failure paths
  • Complete the Unix implementation

Remaining

  • Fix final . / .. handling and trailing-slash semantics
  • Implement Windows support

@Luca388
Luca388 force-pushed the issue-458-repro branch 2 times, most recently from 8db50e6 to fc087c0 Compare August 4, 2026 16:47
@clover2123 clover2123 linked an issue Aug 5, 2026 that may be closed by this pull request
Comment thread src/wasi/WASI02Impl.cpp
return false;
}

std::vector<std::string> parsedComponents;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to duplicate these strings? Could we use substrings for this purpose?

Comment thread src/wasi/WASI02Impl.cpp
path.append(componentPath);

// uv_fs_t req;
// int descriptor = uv_fs_open(NULL, &req, path.c_str(), openFlags, 0666, NULL);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am unsure about changing these functions. We use libuv and uvwasi for maximum portability between platforms as it supports both windows and linux. Dealing directly with system calls might introduce lots of things to maintain.

I think only implementing correct path resolution would be sufficient enough.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that libuv doesn’t provide an openat()-style API for resolving paths relative to a directory FD.

Following your suggestion, I could use uv_fs_realpath() to resolve the path, verify that it remains within the preopen directory, and then open it with uv_fs_open(). However, I think this approach could introduce a TOCTOU vulnerability if the path or a symbolic link changes between the resolution and open operations.

Would this limitation be acceptable here, or is there another mechanism in uvwasi that should be used to avoid it?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wasi 0.1 implementation uses this code:
https://github.com/nodejs/uvwasi/blob/main/src/path_resolver.c#L417

It is partly custom, partly uw. Would be good if we could use only one code path, but this might be too difficult.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WASI 0.2: open-at allows paths to escape preopened directories

3 participants