saintordevil/OSAINT

GitHub: saintordevil/OSAINT

OSAINT 是一款命令行公开链接身份归因工具,从 50 个平台的分享和邀请 URL 中提取标识符并标注身份角色。

Stars: 1 | Forks: 0

# OAINT OSAINT 是一款用于公开分享、邀请、个人资料、预约、活动和 clip URL 的命令行链接归因工具。它会提取受支持链接所暴露的标识符,并标明该身份与链接之间的关系。 这种区别很重要。一个结果可以描述实际的分享者、推荐账号、邀请创建者、clip 创建者、内容所有者、活动主办方,或是个人资料链接的目标。OSAINT 将此报告为 `identity_role`,并将 `actual_sharer` 专门保留给具有经过证实的发送者归因字段的格式。对于分享者和推荐语义,`is_sharer_identity` 为 `true`;对于上下文身份(如所有者、组织者、目标和 artifact 创建者),则为 `false`。 URL 是其编码内容的证据,而不是 URL 本身真实的证明。查询参数和路径 ID 可以被手动编辑。请保留原始来源,并独立佐证重要的身份结论。 ## 2.0.0 版本的更新内容 - 添加了 Stack Exchange 内置的 `/q/{post}/{user}` 和 `/a/{post}/{user}` 分享链接。Stack Exchange 在构建此 URL 时会附加点击者的账号 ID,但由于未签名的路径仍然可编辑,因此 OSAINT 将其标记为 `referral_account` 而非发送者的证明。Public API 丰富是可选的。 - 修正了 YouTube 输出,以识别旧版的 Clip 创建者,而不是后来转发该 URL 的人。普通的 Watch、Shorts 和 `si` 链接仍不受支持。 - 从路由中移除了 Telegram 邀请哈希。当前的邀请哈希是不透明的,无法安全解码为公开的创建者 ID。 - 在所有模块中添加了明确的归因角色。 - 强化了 URL 解析能力,以防范相似域名、嵌入式 URL、凭据、不安全的重定向、无限制的下载和停滞的请求。 - 移除了非交互式和 JSON 运行中的装饰性延迟,并确保 TLS worker 在每次命令后都会关闭。 - 扩展了针对路由、解析器、终端安全、重定向处理、退出代码和归因语义的回归测试。 ### 2.0 迁移说明 - 结果现在包含 `identity_role` 和 `is_sharer_identity`,因此集成系统可以区分分享者/推荐信号与上下文账号。 - 以前被错误标记为 `profile_url` 的输入 artifact 链接现在使用 `share_url`。返回的 `profile_url` 指向身份个人资料。 - Microsoft SharePoint 输出现在会保留 `site_slug`,并将推导出的地址标记为 `email_candidate`;它不再将启发式结果呈现为已验证的电子邮件。 - 不再路由 Telegram 邀请哈希,因为当前的哈希是不透明的。 - 这些 schema 和路由修正是此版本使用主版本号的原因。 ## 支持的模块 OSAINT 包含 50 个路由模块。“角色”是指返回身份的含义,并不保证每个实时页面都会暴露每个可选字段。 | 平台 | 角色 | 公开信号 | |---|---|---| | **Stack Exchange** | `referral_account` | 由内置 `/q/` 和 `/a/` 分享链接附加的可编辑、未签名用户 ID | | **Spotify Wrapped** | `actual_sharer` | `shareData.sender_name` 及相关的公开 Wrapped 卡片数据 | | **Instagram** | `sharer_account` | 暴露时与 `igsh` 分享 token 关联的账号数据 | | **TikTok** | `sharer_account` | 启用个人资料分享时,移动端分享页面的 `shareUser` payload | | **Xiaohongshu / RED** | `sharer_account` | 带有配套 App 分享标记的内容 URL 上的有效 `appuid`;单独的 `shareRedId` 只是元数据,不是账号 ID | | **Bilibili** | `sharer_account` | 带有配套 App 分享标记的内容 URL 上的数字 `mid` 或 `share_mid` | | **NetEase Music** | `sharer_account` | 带有内容 ID 的已识别内容路由上的 `userid`;个人资料丰富为尽力而为 | | **Zhihu** | `sharer_account` | 有效的旧版 `utm_member` 值 | | **Pinterest** | `sharer_account` | 与 `pin.it` 分享关联的公开邀请元数据 | | **Substack** | `referral_account` | 笔记预加载数据中的推荐账号 | | **Suno** | `sharer_account` | 与 Suno 分享代码关联的公开账号 | | **Reddit** | `sharer_signal` | 实验性:仅当 `/r/{subreddit}/s/{id}` 响应明确暴露分享者字段时才输出;当前的公开链接通常会关闭失败 | | **Discord** | `invite_creator` | 可用时由公开邀请 API 返回的邀请者对象 | | **Claude** | `share_creator` | 公开分享对话上的创建者元数据 | | **Perplexity** | `thread_author` | 公开搜索线程上的作者元数据 | | **YouTube Clips** | `clip_creator` | 现有 Clip 页面上的 `clipAttributionRenderer` | | **Twitch Clips** | `clip_creator` | Twitch clip 数据返回的 Clipper 账号 | | **Google Photos** | `album_owner` | 公开分享相册暴露的所有者 actor | | **Partiful** | `event_host` | 公开活动邀请暴露的主办方账号 | | **Lu.ma** | `event_host` | 公开活动页面暴露的主办方账号 | | **Eventbrite** | `event_organizer` | 公开活动页面暴露的组织者元数据 | | **Microsoft Teams** | `meeting_organizer` | 会议 `context` 字段中的组织者和租户 ID | | **Microsoft SharePoint** | `sharepoint_owner` | 个人站点 slug 和明确标记的启发式电子邮件候选 | | **WhatsApp** | `recipient_account` | 点击聊天 URL 目标的电话号码 | | **QQ Contact** | `recipient_account` | WPA 联系人 URL 目标的 QQ 号码 | | **Steam Trade** | `trade_offer_owner` | 用户创建的交易报价 URL 中的账号 ID 和 token | | **OneDrive Personal** | `storage_owner` | 个人存储 CID 或资源所有者容器 | | **Baidu Pan** | `share_owner` | 受支持的旧版 Netdisk 分享链接中的 `uk` 值 | | **Cash App** | `profile_target` | 支付个人资料 URL 中的 Cashtag | | **Venmo** | `profile_target` | 个人资料或二维码 URL 中的用户名或用户 ID | | **PayPal.Me** | `profile_target` | 支付个人资料 handle 和公开元数据 | | **Ko-fi** | `profile_target` | 创建者个人资料 handle 和公开元数据 | | **Buy Me a Coffee** | `profile_target` | 创建者个人资料 handle 和公开元数据 | | **Patreon** | `profile_target` | 创建者个人资料 handle 和公开元数据 | | **Linktree** | `profile_target` | 个人资料 handle 和公开元数据 | | **Beacons** | `profile_target` | 个人资料 handle 和公开元数据 | | **Calendly** | `booking_owner` | 日程安排所有者 slug 和公开元数据 | | **Cal.com** | `booking_owner` | 日程安排所有者用户名和公开元数据 | | **TidyCal** | `booking_owner` | 预约所有者 slug 和公开标题元数据 | | **YouCanBookMe** | `booking_owner` | 预约所有者子域名和公开元数据 | | **SavvyCal** | `booking_owner` | 预约所有者 slug 和公开元数据 | | **Acuity Scheduling** | `booking_owner` | 日程安排 URL 中的数字 `owner` 值 | | **Ticket Tailor** | `event_organizer` | 售票处所有者 slug 和活动 ID | | **Humanitix** | `event_organizer` | 公开活动页面上的组织者元数据 | | **Meetup** | `event_organizer` | 公开活动页面上的群组、活动和主办方元数据 | | **TicketLeap** | `event_organizer` | 活动 URL 中的组织者 slug 和活动 ID | | **Eventzilla** | `event_organizer` | 公开活动页面上的组织者元数据 | | **Universe** | `event_organizer` | 公开活动页面上的组织者元数据 | | **Loom** | `recording_owner` | 公开页面状态中的录制所有者元数据 | | **Medal.tv** | `clip_creator` | 公开 clip 数据中的录制者或发布者元数据 | ## 故意不支持的情况 - **普通 YouTube 链接:** Watch、Shorts 和 `si` 参数无法公开解析为转发该 URL 的人。现有的 YouTube Clip 页面可以暴露创建该 Clip artifact 的人。YouTube [已于 2026 年 4 月停用了新 Clips 的创建](https://support.google.com/youtube/answer/10332730?hl=en-gb),但现有的 Clip URL 仍然可查看。 - **Telegram 邀请链接:** 当前的邀请哈希是不透明的查找值。Telegram 的公开邀请检查结果不会暴露邀请创建者。OSAINT 会拒绝这些链接,而不是从任意 Base64 字节中猜测 ID。 - **普通 Spotify 链接:** Track、album、artist、playlist、`si` 和 `dlsi` 值不被视为发送者身份。仅路由独特的公开 Wrapped 分享卡片格式。 - **仅包含所有者的内容 URL:** 普通的帖子或媒体 URL 不会仅仅因为包含原始创建者的用户名就被视为分享者证据。 ## 要求 - Node.js 20 或更高版本 - Windows、macOS 或 Linux - 在 Windows 上,建议使用带有命令提示符配置文件的 Windows Terminal,以获得最清晰的边框绘制和动画重绘效果 ## 安装 ``` git clone https://github.com/saintordevil/OSAINT.git cd OSAINT npm install ``` ## 用法 始终用引号将 URL 括起来。这对于将 `&` 视为命令分隔符的 shell 是必需的。 ``` # 未签名的 Stack Exchange referral-account 字段 node osaint.js "https://stackoverflow.com/q/11828270/819887" # Link-tied sharer 或 referral 信号 node osaint.js "https://www.instagram.com/reel/example/?igsh=example" node osaint.js "https://www.bilibili.com/video/BVexample?mid=123456&share_session_id=example" node osaint.js "https://music.163.com/song/123/?userid=456" # 以 role 为标签标注的 contextual identities node osaint.js "https://youtube.com/clip/Ugkx..." node osaint.js "https://teams.microsoft.com/l/meetup-join/..." node osaint.js "https://wa.me/447700900000" # 对 Automation 友好的输出 node osaint.js "https://stackoverflow.com/q/11828270/819887" --json node osaint.js "https://stackoverflow.com/q/11828270/819887" -q --json ``` JSON 格式示例: ``` { "user_id": "819887", "identity_role": "referral_account", "is_sharer_identity": true, "identity_confidence": "unsigned_url_claim", "account_validation": "api_confirmed", "post_validation": "api_confirmed", "share_source": "built-in-share-referrer" } ``` 网络信息丰富是尽力而为的。Stack Exchange 在其公共 API 可达时会确认账号和引用的帖子,拒绝确认缺失的 ID,并报告验证状态。当可选的公开元数据不可用时,解析器仍然可以从结构有效的链接中返回离线 ID。 ## 命令 ``` node osaint.js --help node osaint.js --howto node osaint.js --commands node osaint.js --list node osaint.js --test node osaint.js --banner node osaint.js --set-banner=N node osaint.js --animations node osaint.js --anim-demo=N node osaint.js --set-loading=N node osaint.js --set-idle=N ``` ## 安全性与可靠性 - 路由只解析一次 URL,要求使用 HTTPS,并且仅接受完全受支持的主机和路径。相似域名、嵌入式目标 URL、片段、凭据和其他方案都会被拒绝。 - 原生 HTTP 请求具有 15 秒的总超时、5 MiB 的流式下载上限和五次重定向限制。短链接模块将重定向限制在预期的平台主机内。 - TLS 指纹请求链共享 15 秒的预算,在发出请求之前扣除冷启动初始化时间,并在解析前拒绝超过 5 MiB 的正文。当前的 `node-tls-client` API 会在 OSAINT 能够测量之前就具体化响应,因此该 TLS 限制是后缓冲接受上限,而不是流式内存限制。 - 原生 HTTP 请求会预检解析后的地址,并拒绝本地、私有、链路本地、多播和文档范围内的地址。这降低了 SSRF 风险,但不是 DNS 绑定;固定的平台允许列表仍然是主要的信任边界。 - 当响应包含元数据但没有可归因的身份时,动态解析器会关闭失败。 - 终端文本在显示前会去除控制序列。 - 非交互式和 JSON 模式没有装饰性的加载动画延迟。 - 共享的 TLS worker 会在成功、解析器错误、自检、信号和未捕获的失败时关闭。 - OSAINT 仅使用公开可访问的数据,不需要身份验证。 ## 研究笔记 当前的公开探测还检查了 Quora、Wattpad、Kwai/Kuaishou、Douyin、Kick、Snapchat、LINE、WeChat、Lemon8 和其他大型平台。除非能证明其账号语义和安全的公开解析路径,否则不会添加看起来有价值的值。不透明的分析、设备、安装、活动和每次分享的 token 不是身份。 ## 许可证 MIT
标签:Homebrew安装, MITM代理, 代码示例, 底层编程, 数据分析, 文档结构分析, 自定义脚本, 身份溯源, 链接解析