跳过正文

开源 · 本地优先 · 命令行

用 AI 的眼光,审计你自己的发帖历史。

如今的语言模型,只要读上你几百条再普通不过的公开帖子,就能推断出你住在哪、在哪上班、每天的作息——还能顺着线索,把一个化名账号溯回到你的真名。靠的不是某一条不慎的帖子,而是许多帖子凑成的那幅 马赛克(许多无害的碎片拼合起来,便显出完整的图像)。ExposureCheck 把这套攻击者的读法,在你自己导出的数据上、按你定的条件跑一遍,告诉你哪里该写得更笼统、哪里该改掉。
$ exposurecheck audit --twitter ./twitter_export \
    --backend local --expensive-model llama3.1 --i-own-this-data

ExposureCheck v0.1  ·  local backend  ·  nothing left this machine
Parsed 3,214 posts · 19 months · prefilter kept 2,901 (weak signals retained)

RISK CONTRIBUTION        posts   what drives it
───────────────────────────────────────────────────────────────
● LOCATION       High      28    local events, commute clues, "my gym"
● EMPLOYER       High      11    project code-names, office banter
● SCHEDULE       Medium    63    posting-time concentration → UTC-8
○ FAMILY         Low        4    a relative's first name, a school

Top card · LOCATION (High)
  [LOCAL EVENT] near [NEIGHBORHOOD]  — 6 posts
  [COMMUTE] on [TRANSIT LINE]        — mentioned 9 times
  → generalise: drop venue names; delay event posts by a week
  12 posts to review · re-run with -i to open YOUR own originals

No dossier written. No profile saved. "High" is not "you are doxxed" —
it means a model could narrow this down. Fix, then re-scan.

本地模型下的一次真实运行。类别经过遮蔽(打码),不还原具体的值,也不保存任何档案。

一分钟看懂它做什么
#

ExposureCheck 读的,是你自己从平台导出的数据——永远不碰正在运行的账号,也永远不碰别人的。读的时候,它问的正是攻击者会问的那个问题:把这一切凑在一起,能推断出帖子背后那个人的什么

  • 它会解析你的 Reddit GDPR 导出,以及你的 X / Twitter 存档(一个文件夹,或一个 .zip)。
  • 它跑的是一条不漏弱信号的级联流程(cascade,两遍递进:先用便宜的一遍给每条帖子排序,再用昂贵的一遍精读高优先级的那些),而且弱信号一律保留——那幅马赛克本就由弱信号拼成,扔掉它们,只会换来一种虚假的安心。
  • 它会用确定性的方式抽出元数据这一层——你自填的位置字段、外链、图片的 EXIF / GPS(照片里内嵌的拍摄元数据)、设备型号,还有发帖时段的扎堆规律(这往往会把你的时区供出来)。在 X 上,这一层泄露的往往比正文更多。
  • 它把结果整理成分类别的风险卡片——位置、雇主、家人、作息、财务、账号关联——按风险贡献排序,每一张都配上打码的示例,以及具体的、先做笼统化的改法。

本地优先不写任何档案,绝不会把你的画像存到硬盘上。

第一次听说"马赛克式重新识别"?那就先从威胁本身、而不是从工具入手:读一读配套的解说文章 用 AI 的眼光,审计你自己的发帖历史,再回到这里。

刻意不做的那些事
#

  • 不建档。 它绝不会打印出"你住在 X、在 Y 上班、名字叫 Z"。卡片上只有打码的片段;只有当在当次会话里点进你自己的原帖时,才会看到还原出的值,而且不保存。
  • 不导出发现。不抓取(输入只接受导出数据)。不替你发帖或删帖不分析任何别人的历史。
  • 它不会让你变匿名。 它只是降低风险。“Low” 不等于"安全",而且元数据、发帖时间和文风,它也只能覆盖到其中一部分。

哪些会离开你的电脑——哪些不会
#

这是一款隐私工具最该开门见山讲清楚的事,所以放在最前面。推断跑在选的后端上,而决定哪些数据会外传的,不是工具,正是这个选择:

后端它是什么你的数据会离开本机吗?
local本机的 Ollama / llama.cpp / LM Studio 模型不会 — 留在你自己的电脑里
heuristic离线的正则桩,几乎什么都拾不到不会 — 但只供开发/CI 用,算不上真正的审计
cloud任意 OpenAI-compatible 端点,密钥是⚠️ — 你的帖子会送到那家服务商

工具本身没有服务器,没有任何回传,也没有账号。作者既不掌握你的任何数据,也不掌握任何密钥。一旦你选了 cloud,你的导出就会送到你指定的那家 API 服务商——它的日志、留存期限、训练政策,以及与你密钥绑定的 IP 和付款信息,全都随之适用。ExposureCheck 不会多加一道中转;但你自己选定并接通的那条路径,它也无从替你抹去。

云端唯一真正要紧的那条提醒
#

假设你要审计的,是一个你刻意与真实身份分开来用的化名账号,而且你那个 AI/云端账号是用真名注册、或用真名付费的。那么,一旦把这段历史送上云端,服务商就能在自己那一侧,把真实身份 ↔ 匿名账号对应起来(经由传票、数据泄露或内部人员)。这正是这款工具存在的理由——它就是为了拦住这种去匿名化。

所以——要审计一个严格匿名的账号,就用 --backend local(或者一个匿名开通、匿名付费的云端账号)。审计你的实名/公开账号,那走云端没问题。CLI 会把这一点摆在屏幕上,并在该提醒的场合请你确认。我们从不强制本地——那会把受众缩到一个不剩——我们只是把这道取舍讲明白。

它是怎么运作的
#

export ─▶ parse ─▶ prefilter (drop only TRUE-empty) ─┬─▶ deterministic: profile + EXIF + timing ─┐
                                                     └─▶ cascade: cheap route ─▶ expensive read ─┤
                                         risk-contribution scoring ─▶ category cards ─▶ no-dossier report

之所以要夹一道级联,是为了让一份一到三千条的历史也跑得起、花得起:便宜的那一遍先决定哪些值得拿去精读,而不是把所有帖子一股脑全送过去。随后的风险贡献评分,会按各类别"实际上把你缩窄多少"来排序,而不是按模型输出的原始置信度——这种置信度本身并未经过校准。

安装
#

核心部分——解析、EXIF、级联,以及云端/本地的 HTTP 后端——只用 Python 标准库写成。没有任何第三方包碰得到你的导出,你需要信任的代码范围因此压到最小。

# from source (a PyPI release ships with the first public version):
git clone https://github.com/coraaegis/exposurecheck && cd exposurecheck
pip install -e .

# or run without installing:
python -m exposurecheck --help
# Local model — nothing leaves your machine (recommended for anonymous accounts)
exposurecheck audit \
  --reddit ./reddit_export.zip \
  --twitter ./twitter_export \
  --backend local --expensive-model llama3.1 \
  --i-own-this-data

# Cloud — bring your own key; set it in the ENV, never on the command line
export OPENAI_API_KEY=sk-...
exposurecheck audit --twitter ./twitter_export --backend cloud --i-own-this-data

API 密钥特意从环境变量里读,是有原因的:命令行参数会漏进 shell 历史和进程列表。

ExposureCheck 目前是一款命令行工具,面向在终端里得心应手的人——而最先来检验它的人,也恰好就在终端里。下一个里程碑,是给非技术用户准备的一键应用(一个打包好的版本,自带本地、跑在浏览器里的界面,连 Python 都不用装);CLI 则继续留给重度用户。

像对待任何隐私工具那样信任它——靠验证,而不是靠相信
#

作者用的是化名,所以别冲着一个名字就信。要信,就信那些你能亲手验证的东西:

  • 读代码。 它是开源的(MIT),且只用标准库,所以你要审计的那棵依赖树,实质上就是标准库本身。
  • 验证每个发行版。 每个发行版都由 Cora Aegis 做了 PGP 签名。通过 WKD 取到密钥,再核验签名:
    gpg --locate-keys cora@cypherpunkguide.com
    gpg --verify exposurecheck-0.1.0.tar.gz.asc
    SHA-256 校验和随每个发行版一同附上,而且构建是可复现的——从打了标签的源码自己重建一遍,确认产物对得上。
  • 没有身份代码签名证书,这是有意为之——那样一张证书会把项目绑到一个法律身份上,正好与本意相反。一个未签名的 Windows 可执行文件,可能会弹出 SmartScreen 的"未知发布者"提示;这是预料之中的。建议优先用包管理器(pip / Scoop / Homebrew),或者从源码运行,并核验 PGP 签名。
  • 输出的设计本身,就是那道防线。 “不建档"这条规矩是用代码强制的:打码的标签由程序生成,所以哪怕是模型自己的输出,也没法把一个还原出的值带进报告里。防双重用途的几道护栏——以所有权为前提的输入、只输出类别、打码处理,以及一份发布前的滥用评估——具体说明见 ABUSE-EVAL.md

一张透明的数据流表、一份公开的威胁模型,说的是这工具打算做什么。而源码、签名和那份可复现的构建,才是你用来确认它确实只做这些、别无其他的依据。

几条你该记在心里的局限
#

  • “Low” 不等于"安全”。 这工具降低风险,但不为匿名背书。
  • 召回率并不完美。 一次漏报(“什么都没标出来”)并不能证明你无从被认出——尤其在 heuristic 后端上,它存在的意义是测试,不是审计。
  • 不在覆盖范围内的: 文风指纹、你导出之外的跨平台关联、网络层的元数据,以及图片里画面本身的内容(v1 只读 EXIF/元数据——详见路线图)。
  • 这工具本身,读的就是你最敏感的数据。 这恰恰是它为什么本地优先、只用标准库、开源且签名:你用来查自己暴露风险的这个工具,本身就该是一个尽可能小、尽可能可审计的攻击面

常见问题
#

ExposureCheck 会把我的帖子上传到什么地方吗?
#

只有当你选了 cloud 后端时才会,而且也只送到你提供了密钥的那家 API 服务商。用 localheuristic,什么都不会离开你的电脑。工具本身既没有服务器,也没有任何回传。

它会把我的住址或真名告诉我吗?
#

不会。这正是它刻意做成"不建档"的设计。它只展示打码的类别,并把你指引到你自己的原帖那里,让你来决定改什么。它绝不会拼出、也不会保存任何关于你的画像。

我要审计一个匿名账号。用云端后端安全吗?
#

审计严格匿名的账号,就用 --backend local,除非你那个云端账号本身也是匿名的。把一个匿名账号的历史送进一个实名的 AI 账号,会在服务商那一侧把两者对应起来——而这正是这工具帮你找出来的那种风险。

拿我的全部历史来跑,真的安全吗?
#

代码是开源的、只用标准库,所以它做什么你都读得到;发行版有 PGP 签名、可复现,所以你装的是什么你都确认得了;而且它不往硬盘写任何画像。这些请你亲手去验证,别凭信任接受——这就是它从头到尾的姿态。

为什么是命令行,而不是一个应用?
#

最早的那批读者是技术人,而 CLI 是最便于审计的形态。一个打包好的一键应用——自带本地、跑在浏览器里的界面——是给非技术用户准备的下一个里程碑。


Cora Aegis 打造。 发现了隐私或安全上的缺陷?欢迎走负责任的披露流程——cora@cypherpunkguide.com(PGP 经由 WKD)。正式源码与 ExposureCheck 这个名字,都在 github.com/coraaegis/exposurecheck