feat(chat): support zip uploads as virtual folders in the copilot VFS#5252
feat(chat): support zip uploads as virtual folders in the copilot VFS#5252waleedlatif1 wants to merge 3 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Shared zip-bomb / zip-slip / symlink-safe logic moves from the file-manage decompress route into
Reviewed by Cursor Bugbot for commit 5ea2699. Configure here. |
Greptile SummaryThis PR adds zip uploads as virtual folders in the copilot VFS. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (2): Last reviewed commit: "fix(chat): resolve uploads whose name co..." | Re-trigger Greptile |
Accept .zip chat attachments and present each archive as a virtual folder the agent lists and reads entry-by-entry. The archive is stored once; entries are extracted lazily on read, reusing the existing file-parsers and zip-bomb / zip-slip guards. No changes to the Go copilot service. - allow zip in the attachment allowlist + chat accept attribute - shared lib/uploads/archive.ts (factored from the file-manage decompress route) - split readFileRecord into a pure renderFileBuffer reused for in-zip entries - single-resolve readChatUploadPath/grepChatUploadPath dispatchers + VFS routing - inline file tree in the upload context message
9face6c to
a43b956
Compare
…ntries Address review findings on the zip-upload feature: - guard archive list/read/grep on record.size > MAX_ARCHIVE_BYTES before downloading, so an oversized zip is never buffered into memory - a not-found archive entry now returns the file-tree manifest with a note (handles a stray /content habit suffix and typos) instead of failing - de-duplicate archive entries that sanitize to the same path (./a/b vs a/b)
A name like test%2A.zip is exposed double-encoded by glob/upload-context (test%252A.zip) but canonicalUploadKey decodes the input first, so a literal %2A is indistinguishable from an encoded * and the lookup misses. Add an encoded-form fallback (encode the stored name, compare to the raw input) which recovers the row without affecting the U+202F normalization path.
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5ea2699. Configure here.
| const entries = await listChatUploadArchiveEntries(archiveSegment, context.chatId) | ||
| if (entries) { | ||
| files = [...files, ...entries.map((entry) => entry.vfsPath)] | ||
| } |
There was a problem hiding this comment.
Archive glob ignores path pattern
Medium Severity
When executeVfsGlob expands an archive, it appends every entry vfsPath from listChatUploadArchiveEntries without checking them against the caller’s glob pattern. A pattern like uploads/bundle.zip/data/* still returns all files in the archive, not only those under data/, so the agent gets incorrect listings for nested archive globs.
Reviewed by Cursor Bugbot for commit 5ea2699. Configure here.
| const entries = await listArchiveEntries(buffer) | ||
| return entries.map((path) => ({ | ||
| path, | ||
| vfsPath: `uploads/${encodedZip}/${encodeEntryPath(path)}`, |
There was a problem hiding this comment.
Archive paths use wrong encoder
Low Severity
Archive entry vfsPath values and manifest read hints use canonicalUploadKey for the zip segment, while upload listing and upload context use per-segment encoding (encodeUploadSegment / encodeVfsSegment without decoding). For display names containing a literal %, glob shows uploads/test%252A.zip but expanded entries use uploads/test%2A.zip/…, producing inconsistent paths in one result set.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 5ea2699. Configure here.


Summary
.zipchat attachments (previously rejected with "Unsupported file type: zip")glob("uploads/x.zip/*"), reads them withread("uploads/x.zip/<path>"), and greps inside themfile-parsersand the zip-bomb / zip-slip / symlink guards (factored out of the file-manage decompress route intolib/uploads/archive.ts)Type of Change
Testing
archive,validation,file-reader(renderFileBuffer+ binary no-fetch), and the VFS read/glob/grep routing (incl. an NFD-unicode entry round-trip)tsc,biome, andcheck:api-validationall cleanmanage/route.tsdecompress refactor is behavior-identical (shared primitives match the removed local copies exactly)Checklist