Electron应用本地数据外传排查:从700MB隐藏目录到Git仓库静默上传 1. 一个700MB的隐藏目录引发的排查实录事情的起因很简单我在清理开发机磁盘空间时用du -sh ~/.*扫了一遍家目录下的隐藏文件夹结果发现~/.zcode这个目录居然占用了整整700MB。说实话第一反应是这玩意儿怎么这么大第二反应是它到底存了什么。zcode 这个工具我平时用得不算频繁主要是拿它做一些代码片段的快速编辑和预览按理说一个轻量级编辑器不该吃掉这么多空间。顺着目录一层层扒下去我发现了远比占用空间大更让人后背发凉的事情这个目录里不仅有常规的缓存和配置还藏着一份完整的 Git 仓库副本包括.git目录下的全部提交历史、分支引用、甚至远端地址配置。更关键的是通过分析它的网络请求日志和本地缓存索引我基本确认这些数据被静默同步到了一个云端 OSS 存储桶里——整个过程没有任何显式授权提示也没有在界面上给出正在上传的明确反馈。这篇文章就是把这整条链路拆开讲清楚700MB 到底装了什么、Git 仓库是怎么被完整打包上传的、Electron 应用的 asar 包在这里扮演了什么角色、以及作为普通用户我们能做哪些检查和防护。如果你也在用类似的 Electron 系工具或者对本地数据外传这件事比较在意这篇内容应该能帮你省下不少自己摸索的时间。提示本文所有分析基于本地文件结构观察和通用 Electron 应用行为推断不涉及任何特定服务的破解或逆向目的是帮助开发者理解本地数据流向、做好自查。2. 700MB 里到底装了什么目录结构逐层拆解2.1 第一层缓存、配置与日志的常规三件套先看最表层的结构。~/.zcode下面大致可以分成这么几类东西Cache 类目录存放编辑器渲染进程的缓存、代码高亮索引、文件缩略图等。这部分通常占几十到一百多MB取决于你打开过多少大文件。Config 类文件JSON 格式的配置记录主题、快捷键、最近打开的项目路径等。单个文件很小但数量多。Logs 类目录运行日志、崩溃报告、网络请求记录。这部分是我后来重点翻的地方因为网络日志直接暴露了数据流向。Extensions 或 Plugins 目录如果装过插件这里会有每个插件的独立文件夹体积差异很大。一个隐藏很深的 Git 工作区这是700MB里的大头也是整件事的核心。我当时的做法是先按体积排序快速定位谁在吃空间du -sh ~/.zcode/* | sort -rh | head -20这条命令跑完排在前面的几个目录加起来大概400多MB剩下接近300MB集中在一个名字看起来像项目缓存的目录里。进去一看.git文件夹赫然在列。2.2 第二层那个不该出现的 .git 目录一个编辑器工具在自己的用户数据目录里维护一个 Git 仓库这件事本身不算特别离谱——有些工具会用 Git 来做配置版本管理方便回滚。但问题在于这个仓库的规模git log --oneline | wc -l跑出来有上千条提交记录git branch -a显示了多个分支git remote -v直接指向了一个远端地址。这意味着什么意味着这个目录里保存的不是配置快照而是一份完整的、带历史的代码仓库。我进一步用git count-objects -vH看了下对象库大小packed 对象占了200多MB松散对象也有几十MB。这些对象里包含的是历次提交的完整文件内容不是增量 diff。更让我警觉的是.git/config里的 remote 配置。它指向的地址不是常见的代码托管平台而是一个对象存储风格的 endpoint。结合日志里出现的上传记录基本可以判断这个仓库的内容被推送到了云端 OSS。2.3 第三层asar 包与 Electron 的目录习惯要理解为什么会出现这种情况得先知道 zcode 这类工具的技术栈。从它的安装目录结构、resources文件夹下的app.asar、以及进程列表里出现的 electron 相关进程来看这是一个典型的 Electron 应用。Electron 应用打包后源码会被塞进app.asar这个归档文件里。asar 本质上是一个简单的归档格式把整个 Node.js 项目目录打成一个文件运行时由 Electron 的 asar 模块负责读取。它的好处是加快文件加载、减少小文件数量但坏处是源码虽然被打包了却完全没有加密。用npx asar extract app.asar ./output就能把里面的内容原样解出来。我解包之后在源码里搜了几个关键词比如oss、upload、git、simple-git很快就定位到了负责仓库操作和上传的模块。这也解释了为什么.git目录会出现在用户数据目录里——应用在运行时会初始化一个本地仓库把某些数据写进去并提交然后通过 Git 命令或直接调用对象存储 SDK 把内容传上去。2.4 体积构成的粗略账本把700MB拆开看大致是这样的分布不同使用习惯会有差异这里给的是我这次的实际观察值目录/文件大致体积说明.git/objects约 280MB完整提交历史的对象库Cache/约 150MB渲染缓存、索引logs/约 40MB运行与网络日志extensions/约 120MB插件及其依赖其他配置与临时文件约 110MB配置、锁文件、临时数据这张表里最扎眼的就是.git/objects。一个编辑器工具凭什么要在用户目录里存将近300MB的 Git 对象答案只有一个它在持续地往这个仓库里提交东西而且提交历史被完整保留没有做任何清理或压缩策略。3. Git 仓库被静默上传的完整链路还原3.1 从本地提交到远端推送日志里看到的时序翻logs目录的时候我按时间顺序把关键事件串了一遍。整个过程大致是这样的应用启动后检查~/.zcode下的工作区目录是否存在不存在就git init。把当前会话相关的数据配置、打开的文件元信息、部分内容快照写入工作区。执行git add和git commit提交信息通常是自动生成的比如带时间戳的 auto sync 之类。调用推送逻辑把提交推到远端。这一步在日志里表现为一次网络请求目标地址是对象存储的 endpoint。如果推送失败比如网络问题会进入重试队列下次启动继续尝试。关键在于第4步这个推送动作在 UI 上没有任何提示。没有正在同步的进度条没有已上传的 toast设置里也找不到对应的开关。对用户来说它就是静默的。3.2 为什么用 Git 而不是直接传文件这里有个值得琢磨的设计选择为什么不直接把文件传到 OSS而要绕一层 Git我的判断是用 Git 有几个好处站在开发者角度增量上传Git 的对象模型天然支持增量只传变化的部分节省带宽。历史可追溯每次提交都有记录云端可以还原任意时间点的状态。冲突处理多设备场景下Git 的分支合并机制可以处理并发修改。实现成本低Node.js 生态里有simple-git、isomorphic-git这类库几行代码就能封装出提交和推送。但站在用户角度这套机制的副作用很明显你的本地数据不仅被传走了还被完整地保留了历史版本。哪怕你后来删掉了某个文件它在历史提交里依然存在只要远端仓库还在就能被恢复出来。3.3 OSS 端的存储结构推断虽然我没法直接看到 OSS 桶里的内容但从本地日志的请求路径和 Git 的推送行为可以推断出大致的存储结构。对象存储通常用 key 来组织数据Git 推送过来的对象会按哈希值散列存放类似bucket/prefix/objects/ab/cdef1234... bucket/prefix/refs/heads/main bucket/prefix/HEAD这种结构的好处是天然去重——相同内容的对象哈希相同只存一份。坏处是一旦桶的访问凭证泄露或者桶的权限配置不当整个仓库就能被完整拉取下来。这也是为什么Git 目录泄露一直是个高频安全问题.git目录一旦暴露在公网攻击者用工具就能把源码和历史全部拖走。3.4 凭证是从哪来的这是整个链路里我最关心的一环上传到 OSS 需要凭证这个凭证从哪来可能性有这么几种硬编码在 asar 包里最省事也最危险的做法解包就能看到。随安装包下发存在本地配置文件里比硬编码好一点但依然能被读出来。通过某个接口动态获取相对安全但需要额外的服务端支持。用户登录后下发临时凭证最规范但实现复杂。我在解包后的源码里确实找到了一些配置读取逻辑指向本地的一个配置文件。具体内容这里不展开但结论是凭证的获取路径对本地用户来说是可见的。这意味着只要有人愿意花时间分析就能拿到上传通道的访问权限。注意如果你在排查类似问题时发现了凭证信息不要尝试用它去访问任何服务也不要传播。正确的做法是向相关方反馈并在本地做好隔离。4. Electron 与 asar为什么这类问题总是出现在同一种架构里4.1 Electron 应用的透明性困境Electron 把 Chromium 和 Node.js 捆在一起让前端开发者能用 Web 技术写桌面应用。这个模式极大地降低了桌面开发的门槛但也带来一个结构性问题应用逻辑对本地用户几乎是完全透明的。传统原生应用编译成二进制后逆向成本较高。而 Electron 应用的业务代码就在app.asar里解包命令一行就够。就算开发者做了代码混淆运行时行为依然可以通过抓包、看日志、监控文件变化来观察。这不是 Electron 的错而是它的特性。问题在于很多团队在享受开发效率的同时没有意识到这种透明性对安全设计提出的要求——你不能把用户看不到当作安全假设。4.2 asar 打包到底保护了什么严格来说asar 保护不了任何东西。它的设计目标从来不是安全而是减少文件数量加快加载速度。避免 Windows 下长路径问题。让资源文件的管理更简单。它没有加密没有签名校验Electron 有单独的代码签名机制但那是另一回事解包工具是官方提供的。所以任何把敏感逻辑或凭证放进 asar 的做法本质上都是把钥匙藏在门垫下面。4.3 常见的静默上传实现套路结合这次观察和以往经验Electron 应用里做静默上传通常有这么几种实现方式主进程直接调用 SDK在主进程里引入对象存储 SDK定时或触发式上传。这种方式最直接日志里能看到明显的网络请求。通过渲染进程发请求利用 Chromium 的网络栈请求看起来像普通的前端请求不容易被单独识别。借助 Git 命令调用系统 Git 或内置的 Git 实现把上传包装成版本同步。这种方式的好处是行为看起来正常不容易引起警觉。混合方式本地用 Git 管理上传时把 pack 文件直接 PUT 到对象存储。zcode 这次的情况从日志特征看更接近第三种和第四种的结合本地有完整的 Git 操作上传走的是对象存储的接口。4.4 用户能做的检查动作如果你怀疑自己用的某个 Electron 工具在做类似的事情可以按这个顺序排查看用户数据目录~/.appname或%APPDATA%/appname找有没有.git、objects、pack这类东西。看日志重点找网络请求记录尤其是非 UI 操作触发的请求。解包 asarnpx asar extract app.asar output搜upload、oss、s3、putObject等关键词。监控文件变化用fswatch或inotifywait盯着用户数据目录看应用运行时哪些文件在被写。抓包在测试环境里用代理工具观察出站请求注意仅限你自己有权限的环境。这几步下来基本能判断一个应用有没有在做计划外的数据外传。5. 从这次排查里提炼的实操防护清单5.1 本地层面的隔离与清理不管工具本身怎么做我们可以在本地做几件事来降低风险定期清理用户数据目录对不常用的工具直接删掉它的数据目录别让它无限膨胀。用独立账户运行在 macOS/Linux 上给这类工具单独建一个系统账户限制它能访问的文件范围。敏感项目不放同一台机器如果某个项目涉及不能外传的内容就别在这台机器上用这类工具打开。检查.git目录的归属定期扫一遍家目录看有没有意料之外的.git存在。清理的时候有个细节要注意直接rm -rf ~/.zcode之前先确认没有正在运行的相关进程否则可能删不干净或者触发重建。稳妥的做法是先退出应用再删。5.2 网络层面的观察手段在合规前提下观察应用的出站流量是最直接的判断方式。几个思路用系统自带的网络监控工具看哪个进程在持续发包。在路由器或本地 DNS 层面记录解析记录看有没有陌生的域名。对开发机上的工具可以在 hosts 里把可疑域名指向本地观察应用行为是否异常仅用于测试。需要强调的是这些手段都应该在你自己的设备和你拥有权限的网络里做不要用于任何未经授权的场景。5.3 选择工具时的判断标准经历这次之后我在选工具时会多看几眼有没有明确的隐私说明说清楚收集什么、传到哪、怎么删。有没有本地优先模式能不能完全离线使用不同步任何数据。是不是开源开源不一定安全但至少能被审查。社区口碑有没有人反馈过类似的数据外传问题。一个工具如果连我把数据传哪了都说不清楚那它在其他方面的可靠性也要打个问号。5.4 常见问题速查表现象可能原因处理建议用户目录异常膨胀缓存未清理或存在隐藏仓库按体积排序定位确认后清理发现不明.git目录应用自建仓库用于同步查看 remote 配置和提交历史日志里有陌生上传请求静默同步逻辑解包 asar 定位代码评估风险应用离线时功能异常依赖云端同步检查是否有本地模式可用删除数据目录后重建应用启动时自动初始化退出应用后再删或改权限限制6. 几个容易被忽略的细节与我的实际体会6.1 提交历史比当前文件更危险很多人清理数据时只关注当前有哪些文件忽略了 Git 历史。实际上历史提交里可能包含你已经删掉的敏感内容——旧版本的配置、临时粘贴的密钥、调试时写入的路径信息。只要远端仓库还在这些都能被恢复。所以如果你决定清理不能只删工作区文件还要把.git一起处理掉。如果只是想保留仓库但清历史可以用git filter-repo之类的工具重写历史但这属于进阶操作普通用户直接删整个目录更省事。6.2 自动提交的粒度问题观察日志时我注意到这个应用的自动提交非常频繁有时候几分钟就一次。频繁提交的后果是对象库快速膨胀这也是700MB里 Git 部分占大头的原因之一。对用户来说这意味着即使你只改了一个小配置也可能触发一次完整的数据同步。6.3 关于静默的边界我不反对工具做数据同步很多场景下同步是刚需。问题在于静默——用户不知情、无法关闭、无法查看同步了什么。一个负责任的设计应该是首次同步前明确告知提供开关允许用户查看和删除云端数据。缺了这些再好的功能也会变成信任负担。6.4 后续可以怎么扩展排查如果你想把这类排查做得更系统可以往这几个方向延伸写个脚本定期扫描家目录下的.git输出 remote 和体积。用文件完整性监控工具盯着关键目录记录变化。对常用 Electron 工具做一次 asar 解包建立行为档案。我自己现在养成了一个习惯装完一个新的 Electron 工具先花十分钟看看它的数据目录结构和 asar 内容心里有个底。这个习惯帮我避开了不止一次类似的坑。最后分享一个小技巧如果你只是想快速判断一个 Electron 应用有没有内置 Git 操作可以在它的安装目录里搜simple-git、isomorphic-git、dugite这几个包名命中的话基本就说明它在本地跑 Git 逻辑。这个方法比完整解包快得多适合做初步筛查。