如果你在 GitHub 上搜索过一些热门技术栈比如openpyxl、modbus或者想找一个好用的脚本大概率会看到这样的仓库名字很吸引人描述很专业但点进去一看代码只有几行README 里全是引导你去某个外部网站的链接甚至直接是广告。这不是偶然。最近一项持续了 106 小时的实时调查揭示了一个惊人的事实GitHub 上高达 64% 的推送push活动都来自一种被称为“推送农场”push-farm的自动化垃圾信息攻击。这个数字在 2023 年曾达到过峰值如今再次卷土重来。这意味着什么意味着你每天在 GitHub 探索、搜索、甚至依赖的“开源项目”生态有超过一半的活跃度可能是虚假的、带有目的的噪音。对于开发者而言这不仅仅是信息污染更直接威胁到代码安全、项目可信度和学习效率。你可能会浪费时间在搜索结果中反复点进毫无价值的垃圾仓库。引入风险不小心克隆或引用了包含恶意代码或后门的“钓鱼”项目。污染数据如果你在做数据分析例如基于 GH Archive这些垃圾推送会严重扭曲真实的开源活动图景。本文将基于这项深入的调查为你彻底拆解“推送农场”的运作黑幕。我们不止于告诉你“是什么”更要讲清楚它如何工作从账号伪造、仓库克隆到自动化推送的完整链条。它为何难以根除利用 GitHub 机制的设计漏洞。它对你有什么具体影响在搜索、协作、安全等层面的真实威胁。你能做什么从个人防范到项目维护的最佳实践。我们将从一个真实的垃圾仓库案例开始一步步还原攻击者的操作路径并给出可落地的识别与应对策略。无论你是普通开发者、开源维护者还是技术决策者这篇文章都将帮助你重新审视并保护你的 GitHub 工作流。1. 推送农场一场针对开源生态的“粉尘攻击”要理解推送农场的危害首先要明白它的本质。它不像传统的 DDoS 攻击那样追求瞬间击垮服务而更像一种“粉尘攻击”Dust Attack——通过海量、微小、低成本的虚假操作污染整个平台的数据层和信誉层。核心目标不是破坏 GitHub而是寄生其上牟取利益。这些利益通常包括SEO 垃圾外链在仓库描述、README、甚至代码注释中嵌入大量链接提升目标网站在搜索引擎中的排名。推广欺诈服务伪装成热门工具或资源引导用户访问钓鱼网站、下载恶意软件或购买虚假服务。刷高账号活跃度制造虚假贡献记录为后续出售“高活跃度”账号做准备这些账号可能被用于更复杂的欺诈或舆论操纵。为什么选择 GitHub因为它完美符合攻击者的所有需求高权重域名github.com在全球搜索引擎中拥有极高的权威度在这里留下的链接“质量分”很高。内容自由托管可以免费创建无数仓库存放任意文本、代码哪怕是垃圾。活跃的社区与 API大量的真实开发者活动为垃圾信息提供了天然的“掩护”而丰富的 API 则为自动化操作提供了便利。相对宽松的初始策略为了鼓励开源协作平台对创建仓库、推送代码等行为的初始风控不会过于严苛这给了攻击者可乘之机。因此推送农场实质上是一种“SEO 攻击”和“信誉滥用”的结合体。它消耗的是 GitHub 的存储、计算资源和最重要的——社区信任。2. 运作链条拆解从“傀儡”账号到“污染”推送一次完整的推送农场攻击是一个高度自动化的工业化流程。我们可以将其拆解为以下几个关键环节2.1 环节一账号储备Bot Accounts攻击者首先需要大量 GitHub 账号。这些账号主要通过以下方式获取自动化注册利用临时邮箱服务和脚本批量注册。购买被盗账号从黑市购买因数据泄露而流出的真实用户账号。劫持低活跃度账号通过撞库或弱口令攻击控制那些疏于维护的真实开发者账号。这些账号就是“农场”里的“傀儡”或“肉鸡”。2.2 环节二仓库创建与克隆Repository Template有了账号下一步是创建用作“载体”的仓库。他们很少从零开始写代码而是寻找热门目标锁定当前热门的技术关键词如python、react、machine learning、script等。克隆真实项目直接 Fork 或克隆一个高星的真实开源仓库。这使垃圾仓库在表面上看起来非常“正常”甚至拥有完整的提交历史和文件结构。注入垃圾内容在克隆的基础上修改README.md加入大量的推广链接、联系方式或广告文本。有时也会在代码文件中插入无关的注释或链接。2.3 环节三自动化推送The Push Farm这是核心环节目的是让这些垃圾仓库“活”起来出现在 GitHub 的活跃动态、搜索列表和 GH Archive 等数据流中。攻击者会编写脚本控制成千上万个傀儡账号定期向这些仓库执行git push操作。推送内容可能只是修改一个无关紧要的文本文件如.gitkeep更新README中的日期或者进行一次无意义的合并提交。推送节奏模拟人类行为在一天的不同时间段、以不固定的间隔进行推送以规避基于频率的简单风控规则。网络伪装使用不同的 IP 地址池代理服务器、云主机来发起请求避免因 IP 被封禁导致整个农场瘫痪。2.4 环节四提升可见度Boosting Visibility单纯的推送还不够需要让目标被人看到。滥用主题和描述在仓库主题Topics和描述中堆砌热门但不相关的关键词以提高在 GitHub 站内搜索和外部搜索引擎的曝光率。伪造互动利用一部分傀儡账号给这些垃圾仓库点 Star星标甚至提交虚假的 Issue 或 Pull Request制造受欢迎的假象。社交工程有时会在其他社区如论坛、社交媒体分享这些仓库的链接伪装成“有用的资源”进行传播。通过这四个环节的循环攻击者能以极低的成本在 GitHub 上制造出巨大的虚假声量。调查中提到的64% 的推送来自此类活动这个数字直观地反映了其规模之庞大。3. 对开发者的真实影响不止是“看着烦”很多开发者觉得只要自己不点进去就没事。但这种想法低估了污染生态的连锁反应。影响层面具体表现潜在风险搜索效率搜索结果前几页被垃圾仓库占据真正优质项目被淹没。浪费大量时间筛选可能错过关键解决方案。代码安全仓库可能包含恶意代码、后门或依赖劫持如篡改package.json。克隆或引用后可能导致开发环境被入侵、数据泄露或成为攻击跳板。项目协作垃圾账号向真实项目提交垃圾 Issue 或 PR干扰维护者。消耗维护者精力污染项目讨论区甚至引入恶意代码。数据分析失真基于 GH Archive 等数据进行的开源趋势分析、研究报告结论被污染。产生误导性的行业洞察影响技术决策和投资判断。平台信任度用户对 GitHub 上项目的整体信任感下降。损害开源协作的基石让新用户对参与开源望而却步。一个典型案例假设你是一个 Python 数据分析新手想学习如何处理 Excel 文件。你在 GitHub 搜索openpyxl example。排在前列的很可能有一个描述为“Openpyxl 完整示例教程包含高级图表和数据分析”的仓库拥有几百个星标。你兴冲冲地git clone下来却发现main.py里只有两行打印语句而README.md里全是引导你去某个“付费教程网站”或“独家工具下载站”的链接。你不仅一无所获还暴露在了网络钓鱼的风险中。4. 如何识别一个“推送农场”仓库作为普通用户我们可以通过一些“蛛丝马迹”来快速识别可疑仓库避免踩坑。以下是一份实用的检查清单4.1 仓库元数据检查账号资料创建者账号头像是否为默认用户名是否是无意义的字符组合如user3847561个人简介是否为空或包含广告仓库名与描述仓库名是否与热门项目高度相似但略有不同例如react-nativevsreact_native_awesome描述是否堆砌了大量关键词且语言不通顺可能是机器翻译主题Topics是否添加了过多、且与仓库内容明显不符的热门主题标签4.2 内容与活动检查README.md这是重灾区。直接滚动到页面底部或查看原始内容。如果发现大段的推广文字、链接尤其是短链接或非技术相关网站基本可以判定为垃圾仓库。代码内容点击进入主要代码文件如src/目录下的文件。如果代码量极少只有几行、结构混乱、或包含大量无关的注释和链接就需要警惕。提交历史Commits查看提交记录。如果历史记录显示为从某个知名仓库一次性 Fork 过来之后只有零星且无意义的提交如“update readme.md”、“fix typo”这很可能是克隆后加工的。星标Stars与复刻Forks如果仓库星标数不少几百但复刻数极少个位数且最近的问题Issues和拉取请求PR都是垃圾信息这可能意味着星标是刷的。动态Pulse与贡献图在仓库的 “Insights” - “Pulse” 页面查看近期活动。如果只有来自一两个账号的、频繁的微小提交这符合推送农场的特征。4.3 利用浏览器插件辅助安装一些 GitHub 增强插件如Refined GitHub它可以帮助你更直观地查看仓库信息有时能过滤掉一些明显的异常信号。总结一下快速判断流程看账号是否像机器人看描述和主题是否关键词堆砌看 README底部是否有广告看代码主体文件是否空洞看提交历史是否单薄且无意义如果满足其中多项建议立即关闭标签页。5. 作为项目维护者如何防御垃圾攻击如果你是一个开源项目的维护者你可能会成为推送农场攻击的“素材来源”被克隆也可能被垃圾 Issue/PR 骚扰。以下是防御策略5.1 加固仓库设置进入仓库的Settings页面进行配置设置议题Issues模板在Settings-General-Issues中启用议题模板。规范的模板能提高提交有效议题的门槛吓退一部分自动化脚本。配置拉取请求PR模板同样设置 PR 模板并要求贡献者签署贡献者许可协议CLA虽然不能完全阻止但能增加攻击成本。管理分支保护规则在Settings-Branches中为重要分支如main设置保护规则。例如要求“通过状态检查后才可合并”、“需要拉取请求审核后才可合并”。这能防止垃圾提交被直接推送到主分支。5.2 利用自动化工具过滤使用 GitHub Actions 进行自动化检查编写工作流当有新 Issue 或 PR 被创建时自动分析其内容。检查提交者是否为新账号或低贡献度账号。检查 Issue/PR 正文中是否包含黑名单中的关键词或链接。如果检测到可疑内容自动添加spam标签并关闭同时发表一条评论。集成第三方机器人例如Danger或Pull Request Labeler等可以根据规则自动标记或处理 PR。设置关键词过滤在Settings-Moderation settings中可以设置隐藏包含特定关键词的评论。5.3 社区管理与举报明确社区行为准则在README或CONTRIBUTING.md中明确写出项目不接受垃圾信息。积极使用举报功能对于确认为垃圾内容的 Issue、PR、评论果断使用 GitHub 的Report功能进行举报。举报时选择 “Spam or abuse”。拉黑恶意用户在用户主页点击 “Block user” 可以阻止该用户再次与你互动。6. 从平台到生态我们能期待什么应对推送农场最终需要平台方、开源社区和开发者共同努力。对 GitHub 平台的期待增强行为模式识别利用机器学习模型更精准地识别出自动化、非人类的推送模式如大量账号从相同 IP 段推送相似内容。提高新账号的初始门槛对于来自高风险 IP 或行为异常的新账号在创建仓库、推送代码时增加验证步骤如 CAPTCHA。优化搜索排名算法降低仅凭近期推送频率的权重更多地考虑仓库的真实质量指标如复刻数、贡献者多样性、Issue/PR 讨论质量等。提供更强大的维护者工具为项目维护者提供一键清理、批量处理疑似垃圾内容的工具降低维护负担。作为开源社区和开发者提高安全意识将“识别垃圾仓库”作为一项基本技能不盲目 Star 或克隆来路不明的项目。贡献真实数据积极为高质量项目提交 Issue、PR参与讨论用真实活动稀释虚假噪音。传播识别知识在团队内部和技术社区分享类似本文的识别方法提高整体免疫力。7. 实战编写一个简单的 GitHub Actions 反垃圾工作流让我们以一个具体的、可落地的方案结束。作为项目维护者你可以部署以下这个基础的 GitHub Actions 工作流来自动化检测并标记可能的垃圾 PR。这个工作流的逻辑是当有新的 PR 被打开时检查提交者的账号创建天数是否过短以及 PR 描述中是否包含常见的垃圾关键词如“free”, “download”, “http://short.link”等。如果满足条件则自动为其添加spam标签并关闭。文件路径.github/workflows/anti-spam-pr.ymlname: Anti-Spam PR Check on: pull_request: types: [opened, edited] jobs: check-spam: runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - name: Check PR for Spam Indicators id: spam-check uses: actions/github-scriptv7 with: script: | const { data: pr } await github.rest.pulls.get({ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.issue.number }); const { data: user } await github.rest.users.getByUsername({ username: pr.user.login }); // 规则1检查账号是否新创建例如小于30天 const accountAgeDays (new Date() - new Date(user.created_at)) / (1000 * 60 * 60 * 24); const isNewAccount accountAgeDays 30; // 规则2检查PR标题或正文是否包含垃圾关键词 const spamKeywords [free download, http://, https://short., click here, make money fast, $$$, 促销, 代刷]; const prText (pr.title pr.body).toLowerCase(); const containsSpam spamKeywords.some(keyword prText.includes(keyword.toLowerCase())); // 规则3检查PR是否来自Fork且修改行数极少可选更严格 const isFromFork pr.head.repo.fork; const changes pr.additions pr.deletions; const isTrivialChangeFromFork isFromFork changes 10; // 综合判断如果满足任意一条规则则标记为可疑 const isSuspicious isNewAccount || containsSpam; // 这里可以加上 || isTrivialChangeFromFork if (isSuspicious) { console.log(Marking PR #${context.issue.number} as suspicious. Reasons: New Account${isNewAccount}, Spam Keywords${containsSpam}); // 添加 spam 标签 await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, labels: [spam] }); // 关闭 PR 并发表评论 await github.rest.issues.update({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, state: closed }); await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: 此拉取请求已被自动标记为垃圾信息并关闭。如果你是合法贡献者请确保你的PR描述清晰且与项目相关并可在新的PR中重新提交。 }); } else { console.log(PR #${context.issue.number} passed the spam check.); }如何使用在你的 GitHub 仓库中创建.github/workflows/目录如果不存在。将上述 YAML 内容保存为anti-spam-pr.yml文件。推送这个文件到你的仓库。GitHub Actions 会自动启用这个工作流。当有新的 PR 时工作流会触发并执行检查。注意事项与自定义调整规则你可以修改spamKeywords列表添加你遇到的常见垃圾词。也可以调整accountAgeDays的阈值。谨慎使用自动关闭 PR 是一个强力操作。建议初期只标记添加spam标签而不自动关闭由维护者人工复核。上述脚本是一个示例生产使用前应在测试仓库充分验证。处理误报任何自动化规则都可能误伤。确保在你的README或贡献指南中说明此规则并为合法贡献者提供申诉渠道如通过 Issue 联系。推送农场 spam 的卷土重来是开源繁荣背后一个不容忽视的阴影。它利用自动化手段以极低的成本污染着我们的协作环境。作为开发者被动抱怨无济于事主动识别和防御才是关键。从今天起在点击 Star 或git clone前多花 30 秒检查一下仓库的“健康度”。作为维护者积极利用平台工具和自动化脚本构筑防线。只有当社区中的大多数人都具备了这种“免疫力”攻击者的成本才会真正变高这场“粉尘攻击”的硝烟才会逐渐散去。