陆鸣

自由开发者 · JavaKit 作者 · ⭐ 2,347 · 敏感词幸存者

DeCensor 插件:让 J**a 重见天日

去年秋天,我在技术论坛上发了一篇帖子,标题是《从 GitHub 难民到 Gitee 敏感词幸存者》。那篇帖子炸出了几百个和我一样被审核系统折磨过的开发者。其中有一个在吉隆坡做前端的人,网名叫 Wei,他留了一条很长的留言,大意是:他的开源组件库叫 AvaUI,因为名字里含有 ava,被 Gitee 拒绝创建仓库。他试了各种变体——AvUIAvaUIAVisionUI——全部被拒。最后他只能把项目改名叫 WeiVision,和原来的名字没有任何关系,所有品牌认知度归零。

他在留言的最后写了一句:“我笑了五分钟,然后哭了。”

我当时在湖南老家的书房里看到这条留言,保温杯里的茶又凉了。我想起自己把 getJavaVersion 改成 getLangVersionLookup 的那个下午,想起那本贴在显示器旁边的《自我审查备忘录》,想起凌晨三点对着天花板发呆的每一个夜晚。我给他回了一条私信:“要不要一起做点什么?”

从两个人的愤怒到一个插件

Wei 几乎秒回。我们打了两个小时的视频电话,各自在屏幕前展示了被审核系统改得面目全非的代码片段。他发现我的 avgScore 变成了 averageScore,我发现他的 lastValue 在 Gitee 页面上显示为 l**tValue。我们笑了一轮,然后沉默了大概十秒钟。Wei 先开口:“如果我们写一个浏览器插件,自动把这些星号恢复成原来的字母呢?”

我说:“那它应该叫 DeCensor。”

那个周末我们就开始写代码。Wei 负责前端界面和 DOM 拦截逻辑,我负责正则规则引擎和替换词库。我们的设计思路很简单:插件在页面加载完成后扫描所有文本节点,如果发现符合特定模式的被屏蔽字符串——比如 J**al**ta**g——就尝试根据上下文和内置词库恢复原词。词库的第一批条目直接来自我的《自我审查备忘录》和 Wei 的仓库命名失败记录。

🔧 DeCensor 词库 v1.0(节选)
· J**aJava
· l**tValuelastValue
· a**gScoreavgScore
· con**rtconvert
· sa**PathsavePath
· 日**用户日活跃用户
· 待**项待办事项

第一个版本只花了三天就写完了。Wei 在他的 Chrome 上测试,打开了 Gitee 上自己的仓库页面,看到 WeiVision 旁边那个被系统强制改名的原始项目名 AvaUI 在插件的作用下重新出现在页面上——虽然只是个视觉上的恢复,但他在视频那头沉默了好几秒,然后说了一句:“它回来了。哪怕只是在我的屏幕上。”

那天晚上我把插件装好,打开了 JTool 的 Gitee 页面。当我看到 getJavaVersion 完整地、没有任何星号地出现在代码高亮里的时候,我觉得自己做了一件比屠龙更值得的事。屠龙是为了夺回过去,而 DeCensor 是为了让未来不再需要屠龙。

从两个人的玩具到十万人的工具

我们没指望这个小插件能有多少用户。最初只是在技术论坛的帖子里附带了一个链接,说“如果你也被误判过,可以试试这个”。第一个周末,下载量是四十七次。Wei 说四十七已经比他预期的多了四十六个。

然后有人把它发到了开发者社群。一个叫“方块鱼”的 B站 UP 主——没错,就是那个带我们屠龙的 MC 主播——在他的动态里提了一嘴 DeCensor,配了一句:“程序员连给自己的变量起名字都要经过 AI 审查?这个插件帮你们把名字抢回来。”那条动态被转发了几千次。第二天早上我醒来,插件下载量跳到了三千多。Wei 发来一条消息:“我们的服务器没事吧?”我回:“我们根本没有服务器,这是纯客户端插件。”他松了一口气。

一个月后,下载量突破两万。我们在 GitHub——不,那时候 GitHub 已经不在了——在 SourceWeave 的测试网上开源了全部代码,收到了来自全球的 pull request。有人贡献了法语和日语的敏感词模式,有人写了一个俄罗斯套娃式的嵌套星号恢复逻辑,还有人专门为 Gitee 的“可疑数字编码”误判写了一个白名单模块。DeCensor 从一个两个人的愤怒,变成了一个社区的姿态。

100k+
已拯救变量名
47
支持语言/平台规则
12k+
周活跃用户
被修复的尊严

不只是变量名

有意思的是,很多用户后来告诉我们,他们用 DeCensor 不只是为了看代码。有人用它恢复技术博客里被误杀的注释,有人用它看被屏蔽的文档标题,还有人在内部论坛上用 DeCensor 读同事发的被系统自动打码的消息。一个用户留言说:“我装这个插件本来是想看 J**a 长什么样,结果我发现整个网页都变正常了。”

Wei 说 DeCensor 让他想起了阿西莫夫的一篇小说——有个机器人在人类说话的时候自动把不雅的词汇消音,后来人们发现,那个机器人把越来越多的词汇判定为不雅,直到所有人都沉默。他说:“DeCensor 就是那个机器人的反面。它把被夺走的词汇,一个一个还回来。”

我看着他打过来的这段话,忽然想起自己很久以前在 JavaKit 的 README 里写过的一句话:“A lightweight Java toolkit for everyday development.” 那时候我从未想过,有一天自己会为了这句话里的“Java”这个单词而战。但人类历史上有太多词被禁止过,太多名字被抹掉过。代码里的变量名或许只是其中最微不足道的一种——但它是我们的语言。是我们用来和机器交谈、和彼此协作的语言。

当这个语言被一群不知道 Java 是什么的 AI 随意篡改时,抵抗就是一种本能。

“DeCensor 不是反审核。它是反遗忘。”

—— 陆鸣,2029年1月15日,湖南老家书房。
保温杯上的字又多了一行:Make Java Great Again。(老严说我俗,但我觉得挺押韵。)

评论 (8)

🐼
林子昂2029-01-15 10:22
装上的第一天,我把公司内部 Gitee 镜像的页面全刷了一遍。之前那些被屏蔽的变量名全回来了,感觉像给代码做了一次白内障手术。老严说这是“程序员的眼镜布”。另外,那个“俄罗斯套娃式嵌套星号恢复逻辑”是我提交的 PR……没想到真的有这种变态审核。
回复
🐟
方块鱼2029-01-15 11:40
哈哈哈哈,我就随口一提,没想到真给你们带了一波流量。话说回来,我把这个插件装在了我剪辑用的浏览器上,发现我之前的视频标题被弹幕网站改了关键字——**挑战 被恢复了。你们这个插件能不能顺便把直播间的超管禁言也给解了?(开玩笑的)
回复
🇲🇾
Wei2029-01-15 12:05
陆哥,这篇文章看得我眼眶又红了。从 AvaUI 变成 WeiVision,再到 DeCensor 让 AvaUI 重新出现在我的浏览器里,这条路走了三年。对了,那个新加入的“法语敏感词模式”贡献者是个在巴黎的华人,他说他遇到的问题是 bitbite(法语单词)被当成英文敏感词拦截了。我们真的不是一个人在战斗。
回复
🌱
陈小满2029-01-15 16:18
陆哥,我在大学图书馆的电脑上装了 DeCensor,然后打开了我的 ClassroomKit 仓库页面。那个被标红的 avgScore 终于变回了正常的颜色。我旁边同学以为我中了彩票。我说:“比中彩票好,我的变量名出狱了。”
回复
老严2029-01-16 09:10
我们团队现在新人入职标配之一就是装 DeCensor。子昂负责的那个俄罗斯套娃 PR 其实是我们整个后端组一起肝出来的。你们知道吗,审核系统有一次把 Class(Java 关键字)给屏蔽了,因为它在某个语境里被判定为“阶级”敏感词。我们把修复规则写进了 v2.1,叫“Class Liberation”。
回复
方槐2029-01-16 18:44
Luming, I installed DeCensor on my browser even though I don't use Gitee. It's a reminder of what we fought for. The German team sends their regards — they've integrated some of the DeCensor regex patterns into our internal code review tool. The dragon is not just in the End; it's in every line of code that gets censored.
回复
🗄️
那个匿名的 Gitee 审核员2029-01-17 01:55
我还是不能透露身份。但我想让你们知道,DeCensor 在内部也被一些人悄悄装上了。不是用来“反审核”,而是用来检查我们自己的误杀率。它间接推动了一次规则更新——虽然离你们期待的改变还很远,但有人在努力。谢谢你们。
回复
🦎
一个被误伤了八年的嵌入式开发者2029-01-18 14:33
我做的是嵌入式 C 开发,有个全局变量叫 avg_temp,被审核系统改了。我为此发了十几封申诉邮件,全部石沉大海。今天装了 DeCensor,那个变量名回来了。我盯着屏幕看了很久。八年。一个变量名等了八年才被正名。谢谢你们没有忘记我们这些写 C 的人。
回复