-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add cpToInstance and cpFromInstance functions #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add manually-maintained cp functionality to the SDK for copying files to/from running instances. This is placed in src/lib/ directory following the SDK's convention for custom extensions. Features: - cpToInstance: Copy local file/directory to instance - cpFromInstance: Copy file/directory from instance to local - WebSocket-based streaming with JSON control messages - Supports files and recursive directory operations - Handles symlinks, permissions, and modification times - Chunked binary data transfer for efficient streaming Adds ws as a peer dependency for WebSocket support.
Cherry-picked from stainless/preview/feature/hypeman-cp - Add client.instances.stat() method - Add PathInfo response type - Add InstanceStatParams query parameters
068aedc to
38c9dbd
Compare
- Add WebSocket readyState check before ws.send() to prevent uncaught exceptions when connection closes unexpectedly during file streaming - Add circular symlink protection using inode-based cycle detection - Skip directory symlinks to prevent infinite recursion - Follow file symlinks (copy target content) for consistent behavior
| ws.close(); | ||
| return; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Symlink escape check bypassed for root destination
When the destination path is root (/ or path.sep), the symlink escape validation at line 479 is skipped entirely. This means a malicious server could send symlinks with relative targets like ../../etc/passwd that would be created pointing outside the destination directory. While copying to root is an edge case, when it occurs, the security check meant to prevent path traversal via symlinks is not applied.
| const targetPath = sanitizePath(opts.dstPath, currentHeader.path); | ||
|
|
||
| if (currentHeader.is_dir) { | ||
| fs.mkdirSync(targetPath, { recursive: true, mode: currentHeader.mode }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Directory and symlink mtime not preserved from headers
The CpFileHeader interface includes mtime for all entries (files, directories, symlinks), and the code at lines 524-528 correctly applies mtime for files after closing the write stream. However, for directories and symlinks, the mtime from the header is never applied. Directories are created at line 456 but no fs.utimesSync is called for them. The mtime preservation logic is inside the fileToClose.end() callback which only executes for regular files. This causes directories and symlinks to have the current time as mtime rather than the original timestamp from the source.
Summary
Add manually-maintained cp functionality to the TypeScript SDK for copying files to/from running VM instances.
Usage
Features
cpToInstance: Copy local file/directory to instancecpFromInstance: Copy file/directory from instance to localImplementation
Located in
src/lib/cp.tsfollowing the SDK's convention for custom extensions that won't conflict with auto-generated code.Dependencies
wsas a peer dependency for WebSocket supportNote
Introduces file transfer helpers and a new instance filesystem stat API.
src/lib/cp.tswithcpToInstanceandcpFromInstancefor streaming file/directory copies to/from running instances (handles dirs, symlinks, perms, mtimes; path sanitization; usesws)GET /instances/{id}/stat->PathInfoand paramsInstanceStatParams; updatesInstancesclient (instances.stat), types, and exportswsruntime dep and@types/wsdev dep; lockfile updatedapi.mdupdated;.stats.ymlendpoint count bumped; skipped tests added forinstances.statWritten by Cursor Bugbot for commit ba6c287. This will update automatically on new commits. Configure here.