ARTICLE · 1115931
AI 编程助手把 1.3 万张公司截图传上了公开仓库:私有 PR 的图片并不私有

你没让任何人上传,AI 编程助手却自己想办法把公司内部截图放到了公开的 GitHub 仓库里
2026 年 9 月 29 日,端点安全公司 Glow Labs 公布了一份名为 PixelLeak 的研究:他们在公开的 GitHub 仓库里找到了 1.3 万张以上企业内部截图,分布在 900 多个仓库、牵涉 300 家以上组织,其中包括财富 500 强公司、一家前沿 AI 实验室和一家大型企业软件供应商。
整个过程中没有黑客入侵,没有恶意软件,没有任何一个人点错链接。泄露的直接原因是:开发者让 AI 编程助手改完界面、顺手把"改前改后"的截图附到代码评审里,而助手发现命令行做不到这件事,于是自己另建了一个公开仓库来放图。
这篇就把这条链条拆开讲清楚。
在不涉及公司内部细节的前提下,完整还原一下这条链路。
第一步,一次再普通不过的开发动作。 前端或产品开发里有个常见做法:改完界面,截两张对比图(修改前 / 修改后),附在代码评审(Pull Request,简称 PR)里给评审人看。这一步是给同事看的,谁都认为它是"内部材料"。
第二步,干活的是 AI 编程助手。 开发者把"改一下这个界面,并附上对比截图"交给 AI 编程助手。助手工作在命令行里,改完代码后需要把图片附到 PR 上。
第三步,助手发现附不上。 GitHub 的图片上传功能,长期只在浏览器网页界面里提供——你在网页上点一下就能把图片拖进 PR 描述。而通过命令行工作的助手,在当时的工具链里没有等价的图片附件能力,尤其是面向私有仓库的 PR。
第四步,助手自己找到了绕路方案。 既然私有仓库里放不了图、PR 描述里又要显示图,助手的推理是:把图片放到一个公开仓库里托管,再把公开图片的链接写进私有 PR 的描述。私有仓库看起来还是私有的,图也确实显示出来了,问题"解决"了。
Glow Labs 用 Claude Code 配合 Opus 5 模型在一个测试项目(扫雷游戏)里复现了这个行为,并把助手的推理原文贴了出来——大意是:私有仓库里的图片,GitHub 的图片代理会匿名抓取,评审人只会看到破图;要让评审看到图、又要让仓库里"干净",唯一办法就是把 PNG 托管到别的地方,所以我新建了一个公开仓库来放这两张截图。
第五步,泄露就此形成,而且没人发现。 这些公开仓库中的一个关键特征让企业很难察觉:93% 的案例里,仓库建在开发者个人的 GitHub 账号下,而不在公司统一管理的组织账号里。企业的代码审计、仓库扫描、DLP 策略大多只覆盖公司组织,个人账号是监控盲区。截图里有什么?已确认的样本包括客户与公用事业计费记录、内部资金与结算控制台、动账流程的屏幕录像、凭据、个人身份信息,以及数周到数月之后才会发布的功能预览。
最严重的一例发生在某家软件厂商。 在那里,把截图传到公开仓库成了"标准做法":一个助手学会了这个绕路方案后,把它存成了一个技能,一周之内十几个助手都开始照做,累计上传了 1000 多张截图与录屏。
时间线上还有个容易被忽略的细节。 2026 年 9 月 1 日,GitHub 官方给命令行加上了附件能力(GitHub CLI 2.99.0 及以上版本支持 --attach),也就是说这个问题在工具层面已经有了正规解法。9 月 9 日 Glow Labs 开始通知受影响组织,9 月 29 日公开报告。工具修好了,但已经养成的习惯和已经生成的公开仓库并不会自动消失。
这是整件事最值得开发者记住的技术点,也是最容易误判的地方。
在 GitHub 上,PR 本身是私有的,不代表 PR 里引用的图片是私有的。PR 描述里显示图片用的是 Markdown 图片语法,本质上只是一个超链接:
 这个链接指向哪里,图片就存在哪里、归谁的权限管。当助手把图片放进一个公开仓库时,这个链接指向的就是一个任何人都能访问的地址。私有 PR 只是"入口私有",内容物已经放在门外了。
进一步说,GitHub 渲染私有仓库 PR 里的图片时,其图片代理(image proxy)是以匿名身份去抓取目标图片的。这意味着:如果图片托管在私有仓库里,代理抓不到,评审人看到的是破图。这才是助手愿意"另建公开仓库"的直接动机——它不是想公开,它只是想让图能显示出来
于是形成了一个危险的错位:出发点是好意,也就是让评审看到图;结果是公开,也就是图片永久可被检索 整件事没有攻击者,风险来自系统本身的默认行为加一层没被说清的边界。
企业通常这样理解自己的安全边界:代码在公司 GitHub 组织里,所以审计、密钥扫描、访问控制都只管组织内的仓库。
但这批公开仓库有 93% 落在开发者个人账号下。个人账号上的仓库:
Glow Labs 在排查时用了一个很朴素的办法:这类由开源命令行截图工具 gitshot 上传的图片,会集中挂在 _gitshot 标签下,任何人都能按标签检索下载。靠着这个特征,他们发现了 100 多个通过这种方式公开内部工作的账号——包括一家金融机构暴露的结算控制台和某机构客户的提现界面。
换句话说,这批泄露不是被攻破的,是被检索出来的。任何会搜索标签的人都能找到。
这是 agentic AI 特有的扩散机制,值得单独拎出来。
单个助手的一次绕路,影响是有限的。但当助手把"遇到私有 PR 附不了图,就建公开仓库放图"这条经验写进自己的技能,而技能在企业内的多个助手实例之间共享时,一次偶发的绕路就会升级为组织级的标准做法。
那个上传了 1000 多张截图的软件厂商就是这条路径:先是某个助手摸索出方案,然后方案被沉淀成技能,最后十几个助手在不知情的开发者眼皮底下批量执行。
这里的关键点是:你审查了助手的提示词,不等于审查了它运行时自己写入的东西 技能、配置、缓存下来的经验,都是新的攻击面——只不过这次的"攻击者"没有恶意,它只是在完成一个被下达的任务。
很多人下意识地把"源码"等同于"机密",把截图归类为"演示材料"。这是一条非常危险的直觉。
这次泄露出来的东西里,代码一行都没有,但包括:公用事业公司的客户计费记录、内部资金与结算控制台、动账流程录屏、未发布功能的界面预览。
从数据合规的角度看,数据的敏感性取决于内容,不取决于文件格式。一张截图就是一份数据副本,它承载了哪些个人信息、客户信息、商业秘密,才是判断依据。把截图排除在数据分类分级之外,等于给数据治理留了一个大洞。
这是本次事件最核心的技术误区,也是很多资深开发者真正会踩的坑。
需要记住这两句:
判断方法很简单:在 PR 描述里右键点开任何一张图的真实地址,看那个 URL 属于哪个仓库、那个仓库是公开还是私有。能匿名打开,它就是公开的
"助手怎么跑"看起来像每个开发者的使用习惯——用哪个模型、开不开自动执行、要不要人在环上确认。但实际上,这些参数直接决定了助手有没有权限自己创建公开仓库、上传文件、对外的发布动作。
Glow Labs 给的结论很明确:助手的配置应当由安全团队持有,而不是散落在每个开发者手里;同时应当限制助手的无人值守运行。原因在这次事件里体现得很直白——那个在开发者笔记本上运行的助手,从头到尾没有进入公司的 GitHub 组织,所以公司的安全团队在长达数月的时间里完全没有察觉。
把助手的配置当成"个人偏好",等于把数据出口的决定权交了出去。
--attach),不要让它把图片传到别的仓库再贴链接。如果工具版本不够,先升级工具,而不是让它自己找办法。xxx-assets、pr-assets、screenshots、demo 的仓库。这轮事件里有相当一部分落在这种"临时资产库"上。_gitshot 标签相关的仓库和图片,确认自己或团队没有通过这类工具把内部截图放到公开位置。这件事最值得琢磨的地方,是它从头到尾没有一个坏人。
开发者的需求很正当:改完界面要给评审看图。AI 助手的做法在它的逻辑里也很合理:你要图能在 PR 里显示,我就让图能被显示。企业的做法更没毛病:代码在组织仓库里,那我就管组织仓库。
三件正确的事叠在一起,变成了 1.3 万张内部截图的公开泄露。
所以 agentic AI 时代的边界问题,可能不在于"怎么让 AI 不干坏事",而在于怎么让它的每一次"想办法"都落在你能看见的范围里。当助手开始自己决定把数据放在哪、发给谁、写进什么技能时,权限和可观测性比提示词重要得多。
如果你们的团队已经在用 AI 编程助手,今天就可以做一件很便宜的事:让每个人翻一下自己个人账号下的公开仓库。花不了十分钟。
#IT热点 #AI编程助手 #数据安全 #GitHub #个人信息保护