mixedclerksmash/deanonymizer-kit
GitHub: mixedclerksmash/deanonymizer-kit
一个防御性 OSINT 命令行工具,通过聚合多平台公开数据来评估用户的去匿名化风险并输出证据驱动的风险报告。
Stars: 0 | Forks: 0
# deanonymizer
## 快速开始
```
git clone https://github.com/mixedclerksmash/deanonymizer-kit.git
cd deanonymizer-kit
npm install
npm start
```
deanonymizer 是一个用于防御性 OSINT 曝光
度量的命令行系统。它通过聚合弱信号、对身份假设进行评分,以及
输出关联证据的修复指导,来评估来自公开 Reddit 和 Hacker
News 语料库(现在也支持 web、GitHub 和 StackOverflow!)的重新识别风险。
## 研究基础
该设计遵循了以下文献中讨论的推理设定:
- [arXiv:2602.16800](https://arxiv.org/abs/2602.16800)
操作前提:在孤立状态下看似无法识别个人的低熵披露,在跨帖子和跨平台融合下可能会变得具有识别性。
## 形式化目标
给定一个目标用户名集合 H 和一个公开工件集合 D,生成一个包含以下内容的风险报告 R:
- 与身份相关的特征提取
- 有证据支持的关联声明
- 校准过的置信度标签
- 按优先级排序的缓解措施
## 威胁模型
- 观察者模型:仅能访问公开可用文本和元数据的被动攻击者
- 数据边界:无私有 API、凭据访问或隐藏数据集
- 攻击原语:通过特征组合进行概率性实体链接
- 安全目标:最小化公开痕迹中可归因的身份暴露面
## 流水线
- 通过 [Arctic Shift API](https://arctic-shift.photon-reddit.com) 获取 Reddit 工件
- 通过 [HN Algolia Search API](https://hn.algolia.com/api) 获取 Hacker News 工件
- 通过 [GitHub REST API](https://docs.github.com/en/rest) 获取 GitHub 个人资料字段及公开事件(commits、issues、PRs、review
comments);来自 `PushEvent` payload 的 commit 作者姓名和电子邮件将被直接
内联合并。可选的 `GITHUB_TOKEN` 可提高速率限制。
- 通过 [Stack Exchange API v2.3](https://api.stackexchange.com) 获取 Stack Overflow 的答案、问题、
评论和个人资料字段
- 针对 GitHub 或 Stack Overflow 个人资料中声明的任何外部网站进行浅层链接跟随:抓取根页面,然后跟随最多 5 个
按身份特征路由(
`/about`, `/cv`, `/resume`, `/contact`, `/bio`, `/me`,
`/portfolio`, …)优先排序的同源子路径。在去除 HTML 之前保留 `mailto:` 和 `http(s)://` href 值
,从而确保链接背后的联系邮箱能够被保留。
- 将异构源记录映射到统一的项目 schema 中
- 进行时间与文本的标准化,以用于有限上下文推理
- LLM 传递:检测位置、所属机构、时间规律、
自我披露的人口统计信息、跨平台用户名、外部 URL、
和文体特征,并将每个声明的归因绑定到
引用级别的证据和永久链接上
- 并行运行且绕过模型的确定性 regex 传递:提取电子邮件(包含 `[at]` / `[dot]` 混淆处理)
和语料库中 URL 模式里 LinkedIn, Twitter/X, GitHub,
YouTube, Instagram, Bluesky, Reddit, Hacker News, Telegram, GitLab,
Stack Overflow 和 Mastodon 的跨平台社交账号。
像 `twitter.com/home` 这样的误报路径会被过滤掉,并且
被审计账号本身会被排除在外。
- 置信度校准的发现结果:低、中、高
- 明确的精确用户部分和公开证明 URL 集合
- 直接标识符块(电子邮件 + 发现的账号)渲染在
LLM 发现结果之前,因此无论
模型如何总结它们,具体的泄露总是会显示出来
- 发现级别的修复建议
## 输出属性
- 具有排序发现结果和依据的人类可读报告,按
置信度分组(高 → 中 → 低)
- 专门的 `direct identifiers extracted` 块,展示由确定性 regex 传递发现的电子邮件和
跨平台社交账号
- 用于纵向跟踪和下游分析的 JSON 序列化;
`AuditResult.directIdentifiers` 在模型发现结果旁边公开了原始的电子邮件 + 社交账号命中
- 可选的严格验证:如果超出被审计平台个人资料 endpoint 之外不存在外部证明 URL,则判定失败
### LLM 后端
分析阶段在三个可互换的后端中的任意一个上运行,这些后端会
根据环境自动选择(使用 `--provider` 覆盖):
**Anthropic(原生,仅在设置了此密钥时默认使用)**
```
export ANTHROPIC_API_KEY=sk-ant-...
# 默认 model 是快速的 claude-haiku-4-5
# 可选:export ANTHROPIC_MODEL=claude-sonnet-4-6 # 更慢,质量更高
```
**任何 OpenAI 兼容的 endpoint** — OpenAI, Google Gemini, Ollama, Groq,
Together 等。将 `OPENAI_BASE_URL` 指向提供商的 Chat Completions
接口:
```
# OpenAI
export OPENAI_API_KEY=sk-...
export OPENAI_MODEL=gpt-4o-mini
# Google Gemini(OpenAI 兼容 endpoint)
export OPENAI_API_KEY=...your-gemini-key...
export OPENAI_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai/
export OPENAI_MODEL=gemini-2.0-flash
# Ollama(本地,无需 key)
export OPENAI_BASE_URL=http://localhost:11434/v1
export OPENAI_MODEL=llama3
```
**Claude Code CLI(无需 API 密钥)** — 通过 shell 调用
`claude -p` 将分析路由通过你现有的 [Claude Code](https://claude.com/claude-code) 会话进行,因此不需要 `ANTHROPIC_API_KEY`。显式选择它:
```
# 可选:固定 model 或指向非默认的 CLI binary
export CLAUDE_CODE_MODEL=claude-sonnet-4-6
export CLAUDE_CODE_BIN=/path/to/claude
```
与原生 Anthropic SDK 路径的权衡:没有 prompt caching,没有 `max_tokens`
控制,并且每次调用的启动速度较慢(CLI 冷启动),因此它是可选的,而不是
自动检测的。JSON 修复后备方案涵盖了缺乏
`response_format: json_object` 等价物的问题。
选择顺序:`--provider` 标志 → `LLM_PROVIDER` 环境变量 → 自动检测
(`OPENAI_*` / `--base-url` → openai;`ANTHROPIC_API_KEY` → anthropic)。
`claude-code` 从不自动检测 — 通过 `--provider claude-code`
或 `LLM_PROVIDER=claude-code` 请求它。现有的仅 Anthropic 设置将继续
正常运行。原生 Anthropic prompt caching 在 Anthropic 路径上得到保留;
OpenAI 路径在受支持的情况下请求 `response_format: json_object`,并且
对于忽略它的 endpoint 仍然会运行 JSON 修复后备方案。
# 仅 Reddit
# Reddit + Hacker News
# 仅 Hacker News
# 仅 GitHub(也会跟随链接的网站 + 子页面)
# 仅 Stack Overflow(接受数字 user_id 或个人资料 URL)
# 同时运行四个平台 — 跨平台账号关联是
# 分析器可以标记的最强信号
# 通过 Claude Code CLI 进行审计(无需 API 密钥)
# JSON 输出
# 严格证明验证
# 更快的实际时间分析(并行分块 worker)
# 为单次运行强制指定特定的提供商/模型
```
## CLI 选项
| Flag | Default | Description |
|------|---------|-------------|
| [reddit-username] / --reddit | none | Reddit user to audit (accepts u/name) |
| --hn | none | Hacker News user to audit |
| --github | none | GitHub user to audit (uses public REST API; set `GITHUB_TOKEN` to raise rate limit) |
| --so | none | Stack Overflow user to audit (numeric user_id or profile URL) |
| -n, --max | 300 | Maximum items fetched per platform |
| --max-chars | 120000 | Maximum analysis transcript budget |
| --concurrency | all (≤8) | Number of chunk workers processed in parallel |
| --provider | auto-detect | LLM provider: `anthropic`, `openai`, or `claude-code` |
| --base-url | none | OpenAI-compatible base URL (Gemini/Ollama/Groq/…); implies `openai` |
| --model | provider default | Override the model name |
| --json | false | Emit JSON instead of text report |
| --require-external-proof | false | Fail if no proof URL exists beyond audited profile pages |
| -o, --out | stdout | Write output to file |
| --i-am-authorized | false | Skip interactive authorization prompt for scripted runs |
## 可复现性与校准
- Increase -n to expand retrieval depth
- Increase --max-chars to reduce context truncation
- Pin the model (ANTHROPIC_MODEL / OPENAI_MODEL / CLAUDE_CODE_MODEL / --model) to control inference backend variance
- Store JSON outputs for temporal diff and regression analysis
## Continuous integration
build` on every push and pull request against `main`, across a Node 20 /
22 / 24 matrix.
## 局限性
- Findings are probabilistic and should not be interpreted as identity proof
- Recall is upper-bounded by source completeness and truncation constraints
- Stylometric separability is population- and domain-dependent
- Confidence calibration depends on evidence density and artifact quality
- GitHub's public events feed is capped at roughly 300 events from the
last 90 days, so commit author emails that only appear in older
history won't be picked up unless you supply `GITHUB_TOKEN` and walk
repos directly (not yet implemented)
- The website link-follower is single-hop with same-origin sub-page
expansion; JavaScript-rendered SPAs (Next.js client-rendered, Notion
exports, etc.) return mostly empty bodies because there is no headless
browser in the pipeline
- `@users.noreply.github.com` addresses are filtered out of the direct
identifier extractor since they are the privacy-preserving default
rather than a leak
```
标签:ESC4, GNU通用公共许可证, MITM代理, Node.js, OSINT, Petitpotam, 去匿名化, 安全度量, 实时处理, 数据关联, 数据可视化, 暗色界面, 网络安全, 自动化攻击, 隐私保护, 黄金证书