Repository navigation
feat(cli): add archive command for cross-host data transport - #610
Conversation
Bundles each browser's decryption-relevant files + Local State into a <browser-key>/<User Data> zip (forward-slash entries) for cross-host restore.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #610 +/- ##
==========================================
- Coverage 73.63% 73.07% -0.57%
==========================================
Files 67 69 +2
Lines 2989 3112 +123
==========================================
+ Hits 2201 2274 +73
- Misses 591 619 +28
- Partials 197 219 +22
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a new CLI archive command to package decryption-relevant Chromium browser files into a portable zip for cross-host workflows (to be consumed later by restore/keys import), using a <browser-key>/<User Data layout> internal structure and forward-slash zip entries.
Changes:
- Add
hack-browser-data archivecommand andbrowser.BuildArchiveto stage (locked-file-safe) profile artifacts and zip them. - Add layout-preserving
ZipDirand Zip-Slip-protectedUnziphelpers inutils/fileutil. - Update Chromium source path handling to remain slash-canonical for archive layout reproduction, and document the workflow in RFC-013.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| utils/fileutil/fileutil.go | Adds ZipDir (layout-preserving) and Unzip (Zip-Slip checks) utilities for archive/restore flows. |
| rfcs/013-cli-redesign-cross-host.md | Updates RFC status and refines archive/restore layout and workflow notes. |
| cmd/hack-browser-data/main.go | Registers the new archive subcommand. |
| cmd/hack-browser-data/archive.go | Implements the archive CLI command wiring (discover → build archive → log). |
| browser/chromium/source.go | Keeps Chromium relative source paths slash-canonical for archive reuse. |
| browser/chromium/chromium.go | Exposes BrowserKey() and retains rel on resolved paths for archive layout reproduction. |
| browser/chromium/archive.go | Adds ArchiveSources to enumerate per-install/profile sources with forward-slash layout relpaths. |
| browser/chromium/archive_test.go | Tests that ArchiveSources emits forward-slash layout relpaths and includes markers + Local State. |
| browser/archive.go | Adds BuildArchive to stage via filemanager.Session and write the final zip. |
| browser/archive_test.go | Round-trip test for BuildArchive + Unzip validating <key>/<User Data layout> zip layout. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for { | ||
| _, err := io.CopyN(out, rc, 1<<20) | ||
| if errors.Is(err, io.EOF) { | ||
| return nil | ||
| } | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } |
| } | ||
| } | ||
| for _, p := range b.profiles { | ||
| profileRel := filepath.Base(p.profileDir) |
| if err != nil { | ||
| return err | ||
| } | ||
| log.Infof("Archived %d file(s) to %s", n, outputPath) |
| // BuildArchive packs each browser's decryption-relevant files into a zip whose internal layout is | ||
| // <browser-key>/<User Data layout>, so a restore can re-expand it and decrypt with a keys.json. Files | ||
| // are staged through a locked-file session first because Windows holds exclusive SQLite locks. Returns | ||
| // the number of files captured. | ||
| func BuildArchive(browsers []Browser, categories []types.Category, outPath string) (int, error) { |
Drop the phantom <basename>/ level for flat-layout installs (profileDir == root), say "entries" not "files" (count is per source path), and add ZipDir/Unzip (>1MB, empty, Zip-Slip) + flat-layout tests.
| for { | ||
| _, err := io.CopyN(out, rc, 1<<20) | ||
| if errors.Is(err, io.EOF) { | ||
| return nil | ||
| } | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } |
It writes a zip and returns a count; Build prefix clashed with BuildDump, which constructs an in-memory value with no I/O.
Adds the
archivecommand: bundles the decryption-relevant files of each browser plus Local State into a<browser-key>/<User Data>zip (forward-slash entries) for cross-host restore. Chromium-only.Refs #607.