你的 Github 仓库被 DMCA Takedown 后怎么办？
我们的开源项目放在 GitHub 上的仓库由于收到了 DMCA Takedown 投诉被封禁，仓库处于不可访问状态。在解决了这个惊魂事件之后，我们将此中得到的教训和经验分享给大家。
GitHub DMCA
218.20.4.82
很好奇是什么文件侵犯了版权
来自广东广州的 QQ Browser 10.5|Windows 7 用户
2020-04-06T23:33:06.000
223.88.96.20
&lt;script&gt;alert('XSS Inject Test')&lt;/script&gt;
来自河南郑州的 Firefox 108.0|Windows 10 用户
2023-01-18T18:42:26.000
118.249.42.191
都什么年代 还在进行传统XSS注入？
来自湖南长沙的 Chrome 109.0|Windows 10 用户
2023-02-09T09:13:27.000
91.199.84.73
应该是误用某个有版权的图标之类
来自荷兰的 Chrome Mobile 120.0|Android 10 用户
2024-02-04T07:56:37.000
我们的开源项目放在 GitHub 上的仓库由于收到了 DMCA Takedown 投诉被封禁，仓库处于不可访问状态。在解决了这个惊魂事件之后，我们将此中得到的教训和经验分享给大家。
![](/data/attachment/album/201802/23/021721tniukydfunnyikai.jpg)


### 仓库被封禁


在 2018 年 2 月 20 日，我们的开源项目放在 GitHub 上的仓库由于收到了 DMCA Takedown 投诉被封禁，仓库处于不可访问状态。此时在 GitHub 上访问该仓库时，会显示一个公开消息，表明该仓库被封禁的原因。


按照 GitHub DMCA 的规则，GitHub 在确认投诉有效后，会给该仓库的管理员发送一封邮件，提示该仓库需要在 24 小时内清理被投诉的内容，并**回复** GitHub 才行——否则，该仓库会被封禁，禁止任何访问和数据导出。


我们在收到该 Takedown 投诉后，会有 24 小时的时间来响应，但由于过年期间，仓库拥有者没有及时看到邮件，未能及时发现这么严重的通知。因此，在过了 24 小时后， Github 按照 DMCA 的规则，进行了仓库的封禁。


仓库被封禁后，我们发现无法访问。根据封禁消息的提示，发现原来之前仓库内的某个文件出了问题，侵犯了原作者的版权。原作者向 Github 发送了 DMCA 投诉。而由于我们的未及时处理，导致了仓库的最终被封。当我们发现被封时，已经是深夜了。






### 紧急商讨方案


在被封禁后，由于已经超过了 24 小时时限，在这个阶段下， GitHub 的文档中给出的解决方案仅有请求 GitHub 来删除该仓库并根据自己手里的仓库数据重建的方案。但对我们来说，这种方案是不可接受的，因为这种方案会导致丢失所有的 issue、PR、Wiki，以及你本地的仓库和远程的仓库之间的版本差异。


我们在群内先找了更新最全的 fork，找到了一个群友提供的，和上游只差 2 个提交的版本，并将其保存下来，作为最后的自救手段。


此外，在查询 DMCA 的过程中，我了解到 DMCA 除了有 DMCA Takedown 以外，还有一个 DMCA Counter Notice，用于反向解除 DMCA 封禁。



> 
> **DMCA Counter Notice**
> 
> 
> DMCA Counter Notice 用于向服务商发起申诉，说明 DMCA Takedown 投诉为恶意投诉且并无版权问题。
> 
> 
> **延展阅读**
> 
> 
> <https://www.plagiarismtoday.com/2010/06/03/7-common-questions-about-dmca-counter-notices/>
> 
> 
> <https://help.github.com/articles/guide-to-submitting-a-dmca-counter-notice/>
> 
> 
> 


当时考虑到我们已经错过了窗口期，没办法删除 GitHub 上仓库中的特定文件，所以想通过 DMCA Counter Notice 来解除封禁。


为此，我通过 Github 发给我们的邮件，找到了那份侵权文件，并在他的网站中找到了版权拥有者的邮件，发送邮件说明情况，看看能否通过付费获得授权。但其是挪威人，存在时差，所以我们只能边等待，边想办法。


### 山重水复疑无路，柳暗花明又一村


在准备 DMCA Counter Notice 时，我们又向 Github 发送了邮件，说明了中国春节的特殊情况，导致我们没有来得及处理文件，请求给我们一个机会让我们处理这些文件。但是迟迟没有回应，无奈之下，多位成员又以成员身份向 GitHub 发送邮件，请求给予帮助。


令人惊奇的是，经过大约 9 个小时的等待，仓库拥有者的请求邮件似乎开小差了，而各位成员的请求邮件得到了响应。Github 回信给大家说，根据其规则，给出了额外的 24 小时窗口期，让我们处理这些文件（后来经过仔细查阅 GitHub 的 DMCA Takedown 规则，对这种错过了第一次窗口期的情况，可以给予第二个，也是最后一个窗口期）。但是这个开启额外的窗口期，需要仓库的拥有者向 GitHub 发送邮件请求。


然后，我们就以仓库拥有者的身份再次向 GitHub 发送了请求，可能是由于时差的原因，又是几个小时没有回应。


与此同时，我们也收到了版权拥有者的回复。很遗憾，原作者不愿意授权，也不打算收费。好在 Github 给的额外窗口期，让我们有了改正错误的机会。


还好，在焦急的等待之中，我们终于收到了 GitHub 的回复，并同时恢复了仓库的访问——宝贵的 24 小时窗口期。


### 使用 BFG 处理文件


得到了窗口期后，我们开始处理仓库内的文件。


首先，你得清除了现在还在仓库里面的文件，然后再使用下面的方面来清除提交历史中的数据。



> 
> **推荐阅读**
> 
> 
> 以下文章建议按顺序阅读
> 
> 
> <https://help.github.com/articles/removing-sensitive-data-from-a-repository/>
> 
> 
> <https://rtyley.github.io/bfg-repo-cleaner/>
> 
> 
> 


删除 Git 仓库的历史数据有多种方法，一种是使用 `git filter-branch`来处理，但是速度极慢。另外一种就是使用 BFG 来处理，我们采用的是 BFG 来处理（BFG 是`git filter-branch` 首字母的逆转）。



> 
> BFG 需要 Java 的运行环境，如果无法运行，请检查你的本地 Java 环境是否安装，或高于 Java 7 。
> 
> 
> Java 6 需要使用 bfg v1.12.3版本
> 
> 
> 


BFG 的处理过程比较简单，首先，你需要下载 BFG。



```
wget http://repo1.maven.org/maven2/com/madgag/bfg/1.13.0/bfg-1.13.0.jar

```

然后克隆你的仓库到本地，比如 `bestony/test`。



```
git clone --mirror  git://github.com/bestony/test.git

```

克隆时用不用 `--mirror` 模式都可以，但是后续命令上会有所差距，所以我还是推荐大家使用镜像模式，毕竟按照官方的文档走，出现了问题也好搜索。（镜像模式克隆的仓库和远程仓库完全一样，但是不能直接看到仓库里面的文件，而且也不能允许 `git` 的各种命令）


克隆到本地后，执行 BFG 命令来处理文件。



```
cd test.git
java -jar bfg.jar --delete-files "filename"

```


> 
> 这里需要注意的是，`filename` 不支持目录路径，只能是文件名，而不能是 `dir/filename` 这样的形式，所以添加参数时你要注意这个。对于有同样名字的文件却想只删除某个目录的情况，可能就没有办法了。
> 
> 
> 此外，默认情况下， BFG 不会处理最新的提交，它认为你的最新提交应该是干净的（不包含需要删除的敏感数据），如果你要删除的文件是最新的提交（比如你最新的一个提交是删除那些敏感数据），可以加入`--no-blob-protection`参数来强制清除，也可以再添加一个提交，使包含了要被删除文件的提交不是最新的提交。
> 
> 
> 
> ```
> java -jar bfg.jar --delete-files "filename" --no-blob-protection
> 
> ```
> 
> 


BFG 处理完成后，会提示你使用 `git` 命令进行垃圾回收，你需要执行如下命令来操作：



```
cd test.git # 进入目标目录
git reflog expire --expire=now --all && git gc --prune=now --aggressive # 垃圾回收

```


> 
> 这里需要注意的是，如果你删除多个文件，每次删除后执行和多个文件都删除后效果一样，所以建议你删除多个文件后再进行垃圾回收，会更省时一些。
> 
> 
> 


处理完成后，将数据推送到远端即可（需要关闭 GitHub 上仓库设置里面对强制推送的防护）：



```
git push

```

执行完成后，就可以到远端上去看了，你的文件会被删除，相关的提交不会被删除，但是提交里面不包含该文件了。



> 
> 在推送时，可能会提示你有些更改被拒绝了，这些更改如果是和 Pull Request 有关的，你可以不需要在意，这是 GitHub 自身的问题。Github 设定 Pull Request 是只读不可改的。所以我们无法修改这些信息。
> 
> 
> 具体可以参考 <https://github.com/rtyley/bfg-repo-cleaner/issues/36>
> 
> 
> 


至此，我们将文件进行了删除处理，并清除了相关的数据。


### 后续处理


在完成文件及历史数据的删除后，我们将我们的删除结果回复了 Github ，等待 Github 的确认。GitHub 会在 24 小时收到该回复后，会通知投诉方进行确认。如果投诉方无异议，此事就此结束，不会再有下一步动作。如果有异议，则会重新进行此流程。


此外，由于 GitHub 存在垃圾缓存回收的时间差，所以你推送到 GitHub 上的数据虽然并无需要被删除的文件，但是依旧在一定时间内可以看到。这种缓存只能请 GitHub 自行操作删除。此外，与要删除的文件相关的 Pull Request 也需要 GitHub 来删除——因为用户是没有权限删除 Pull Request 的。这些请求也可以一并发给 GitHub 来操作（但似乎 GitHub 并不热衷执行这些请求，只要被投诉的文件访问不到即可，也就是说，如果没有被投诉历史数据，其实或许并不用大动干戈清理历史……）。


这种清除操作还有一个副作用就是，所有之前 fork 的仓库，由于主仓库被封禁而导致各个 fork 仓库的 remote 意外地变为另外一个仓库（该仓库是最早的一个 fork 仓库）。而主仓库恢复之后，我们并没有找到好的办法将 remote 恢复回原来的主仓库。因此，需要所有成员重新 fork 主仓库并从缓慢的 GitHub 克隆到本地。


### 余思


这个惊魂事件当中，我们首先要反思的是，我们对版权问题的认识不足，这是一切问题的根源。因此，这之后，我们对既有数据进行了排查。


其次，GitHub 在这种事件的处置上，我们认为也并不够好。这么严重的处置（整个库封禁），仅仅通过一份普通的邮件通知，而且仅仅给出 24 小时的时间窗口。而 GitHub 其实掌握了仓库拥有者的更可靠、更及时的联系方式，比如说手机短信，也完全可以在 GitHub 的网页界面上以显目的方式提醒。另外，虽然 DMCA 规则中提到了可以容情第二个时间窗口，但是似乎这个附加窗口期是后来才改变的政策，在前面的流程说明中并未提及，很容易忽视。


其三，由于封禁会导致对该仓库的所有访问均不可进行，这不仅包括了提交数据，也包括了并没有存在于 Git 仓库中的 issue、PR 和 Wiki 等数据，而 GitHub 不会让你在封禁的情况下有机会导出这些数据。所以，有机会的话，各种数据还是有个备份的好。


最后，感谢在这个事件中，所有不离不弃支持我们的成员，感谢小白进行的仓库清理工作。


### 相关阅读


* <https://blog.kongfanjian.com/2015/03/02/%E6%B0%B8%E4%B9%85%E5%88%A0%E9%99%A4git%E4%BB%93%E5%BA%93%E4%B8%AD%E7%9A%84%E6%96%87%E4%BB%B6%E4%B8%8E%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95/>
* <https://changkun.us/archives/2017/11/239/>
* <http://debugtalk.com/post/clean-sensitive-data-from-git-history-commits/>
* <http://www.voidcn.com/article/p-njmjnwov-bgk.html>
* <http://www.vicviz.com/githubshang-de-min-gan-shu-ju-de-shan-chu/>
* <https://lightless.me/archives/remove-sensitive-data-on-github.html>
* <http://blog.csdn.net/duandianR/article/details/78843582>
* <https://www.clock.co.uk/insight/deleting-a-git-commit>
* <https://www.jacoballred.com/web-dev/use-bfg-to-completely-remove-a-file-from-your-git-repo/>
* <https://community.atlassian.com/t5/Questions/BFG-for-a-Noob/qaq-p/350944>
* <https://w3guy.com/remove-git-commit-history/>
