- 人工智能
- 搜索引擎
- 本地部署
- 后端
- MCP 服务
【免费下载链接】xerj
XERJ is the new way for AI to search data. Its autoindex capability activates agents to know your data without the token waste of grep and sed. One command indexes code, docs, logs and PDFs for search, RAG, security audits and agent memory, using 40x fewer tokens than grep. Elasticsearch compatible, so existing clients just work.
XERJ 分享链接(xerj share)用一条链接加一个口令,把一个索引的只读搜索权限交给对方:guest key 只能检索和阅读被共享的内容,碰不到节点上的其他任何索引、集群信息或写操作。本文基于源码与 237 项实机安全测试,给出 guest key 权限的完整"能 / 不能"清单和背后的威胁模型。
XERJ 分享链接如何工作:链接 + 口令,数据不出本机
XERJ 是一个为 AI 搜索而生的搜索引擎,autoindex 一条命令就能把代码、文档、日志、PDF 建成可搜索的索引。而分享链接解决的是另一个问题:如何让律师、审计员或同事直接搜你本地的索引,又不需要把数据上传到任何服务。
整个流程只有三步:
# 1. 先给文件夹建索引(本地节点,默认开启认证) xerj brain ~/casefiles # 2. 生成分享链接:打印链接、口令、有效期和吊销方式 xerj share ~/casefiles --label "for Dana" --expires 7d # 3. 对方在浏览器打开链接,输入口令,进入只读"阅览室"对方打开链接、输入口令后,POST /_share/claim会铸造一个普通的 API key,它的唯一角色名为share:<handle>(前缀定义在 share.rs#L195),持有对共享索引的read权限,并随分享一起过期。文档与索引始终留在你的机器上——离开机器的只有对方主动请求查看的搜索结果和文档。
创建分享必须使用节点的admin key,普通 scoped key 会被拒绝(403),防止任何 key"通过铸造分享来扩大自己的权限范围"(share.rs 中的require_superuser)。另外,对--insecure启动的开放节点,xerj share会直接拒绝并退出——因为在一个所有人都能读写的节点上,"只读 guest key"没有任何约束意义。
guest key 能碰什么:完整清单
guest 的"阅览室"界面如下:顶部是只读横幅和到期时间,左边是搜索与结果,右边是文档正文:
以下是 guest key可以调用的全部接口,且只能作用于被共享的索引:
| 能调用 | 作用范围 |
|---|---|
_search、_count、_msearch、_mget | 共享索引 |
GET _doc/{id}(含HEAD) | 共享索引 |
_mapping、_field_caps | 共享索引 |
GET /_graph/{brain}/ego、/overview | 共享的 brain |
GET /、_security/_authenticate、健康检查 | 节点 |
路由白名单的完整定义在 authz.rs#L1408-L1415(GUEST_INDEX_OPS等常量)。
一个值得注意的细节:_all、*这类模式不会被拒绝,而是在 key 实际持有的索引上展开——对 guest 来说,_all就是"你的全部共享索引",绝不会更多。
guest key 绝对不能碰什么:完整清单
| 类别 | 结果 |
|---|---|
| 任何其他索引:按名称、按模式、按别名,或在请求体里指名 | 403,或只返回共享文档 |
| 写操作:index、update、delete、bulk、reindex、refresh、flush、close、改 mapping/settings | 403 |
集群面:_cat/*、_cluster/*、_nodes、_snapshot、_tasks、_stats、_aliases、/v1/metrics、原生/v1/*路由 | 403 |
服务端状态:?scroll=1m(含SCROLL、%73croll编码变体)、_search/scroll、_pit、_async_search | 403 |
| 别人打开的 scroll / point-in-time id 被 guest 拿来用 | 403 |
另一个 brain、写共享 brain、/_memory/* | 403 |
管理分享:GET /_share、POST /_share、DELETE /_share/{handle};铸造 API key | 403 |
Console API(/_xerj-console/api/v1/*) | 401(它只认 session cookie,不认 API key) |
间接路径同样被堵死。实机测试专门验证了这些"绕路"手法,全部失败:termslookup、more_like_this、percolate存储文档、lookup运行时字段在允许的请求里指名私有索引;_msearch头与_mget体指名私有索引;指向私有索引的别名。其中 PIT(point-in-time)尤其讲究:决定搜哪个索引的是请求体里的 PIT id 而不是 URL 路径,所以 authz.rs#L1495 的guest_body_denied会在形状层面拒绝携带pit子句的_search/_msearch请求体——guest 根本开不了 PIT,任何它拿出的 id 都是别人的。
还有两个特殊对象:
autoindex-catalog索引永不授予。它列出节点上的所有语料库,无法按文档过滤,所以无论按名称、在列表里还是经别名指它,POST /_share都返回 400(校验逻辑见 share.rs#L588 的validate_share_index)。- 别名在分享创建时就被"钉住"。分享一个别名,记录的是它当前指向的具体索引;之后把别名重指向别的索引,guest 的权限不会跟着移动或扩大。
两道防线:为什么是 403 而不是一句"抱歉"
guest key 的约束由两层独立机制叠加执行(详见 docs/SECURITY_MODEL.md):
- 索引授权:所有 scoped key 都有的按索引鉴权,在中间件和执行引擎的 index funnel 各检查一次;
- 仅对 guest 生效的路由白名单(authz.rs#L1441 的
guest_route_allowed),在索引判定之前执行。
白名单的设计原则是只能拒绝,永不放行:一个被允许的路由仍要过索引判定,guest 未被授予的索引在允许的路由上照样 403。而且"被识别为 guest"这件事只朝一个方向起作用——只会缩小权限,绝不会放大。
证据:237 项实机安全检查,0 失败
上表每一行都是 share_security_live.py 里的一次真实断言。该测试跑在开启认证、开启 access log 的真实节点上,向所有响应里埋了一句"标记句"(藏在私有索引里),然后确认没有任何一条响应带回它。
2026-09-19 的最终运行结果:passed=237 failed=0,外加"节点日志中不含任何 share id"、"无 store 缓存头"等专项检查全部 PASS;完整记录(含构建信息、CI 与手工隧道运行)见 docs/usecases/share-links/VERIFICATION.md。guest 页面的浏览器端行为则由 share-guest-flow.e2e.mjs 用无头 Chrome 覆盖。
威胁模型:分享链接在防什么
| 威胁 | 挡住它的东西 |
|---|---|
| 有人找到或猜中链接 | share id 是 128 位 CSPRNG 随机数,单凭链接打不开任何东西 |
| 持有链接、暴力猜口令 | 每个分享独立锁定:每分钟 10 次、每小时 30 次;生成的口令是 31 字符集的 8 位,约 39.6 bit 熵,30 天满生命周期也只需 21,600 次猜测就封顶 |
| 节点的磁盘被读取 | shares.json(权限 0600)只存 share id 的 SHA-256 摘要和口令的 Argon2id 哈希;明文口令、share id、guest key 均不落盘、不进审计日志 |
| 链接泄漏进日志 | share id 走 URL fragment(浏览器不会发给服务器),再走POST /_share/claim的请求体而不是路径——access log、反向代理、隧道边缘默认记录的正是路径 |
| 代理或浏览器缓存凭证 | 所有/_share响应(含 401/403)和所有 guest key 的响应都带Cache-Control: no-store |
| 恶意文档攻击 guest | 见下图 |
| 垃圾流量把真 guest 锁死 | 已知分享按分享计数、未知 id 按来源地址计数,两套限流不叠加,垃圾流量无法借隧道把真 guest 挤掉 |
文档文本本身被视为敌意输入。guest 页面只用textContent放置内容——没有innerHTML、eval或 HTML 解析,HTML 邮件正文按源码文本显示,文档里的 URL 不会被变成可点击链接;页面本身还带default-src 'none'的 CSP 和X-Frame-Options: DENY。测试用的 XSS 探针邮件被完整"无害化"地展示为纯文本:
坦诚相待:分享链接不防什么
安全文档最诚实的部分是边界。XERJ 明确列出以下不在保护范围:
- 防不了 guest 本人:读权限就是读权限,对方可以复制、截图、重录任何能看到的内容,没有水印或下载控制。
- 没有逐文档 / 逐字段限制:分享授予的是整个索引。文件夹里有不该给 TA 看的东西?那就索引一个没有的文件夹。
- 链接和口令发在同一个渠道:谁同时拿到两样东西,谁就是 guest,直到过期、用尽或被
--revoke。 - 链路观察者:本机回环链接是明文 http;
--tunnel链接的 TLS 由 Cloudflare 终结,Cloudflare 理论上能读到口令、guest key 和文档(命令行打印链接时会明确提示这一点)。 - 被攻陷的 guest 浏览器:guest key 存在该标签页的
sessionStorage,关页或登出前持续有效。 - 成功的读取只被部分审计:审计日志记录所有 claim 结果、所有
_search和所有被 403 的请求,但不记录成功的_msearch、_mget、_count、_mapping、_field_caps、GET _doc——guest 可以用它们读完整共享索引而不留痕。
为什么 guest 用链接+口令,而不是 passkey
Console 自己的登录是 passkey(见下图的登录页)。但 passkey 绑定到创建它的主机名上,而--tunnel每次启动都是全新的随机主机名——通过隧道注册的 passkey 下次就失效了。所以 guest 的凭证路径是"链接 + 口令",而未来若要支持 guest passkey,前置条件是稳定主机名(自有域名隧道或反向代理 +--public-url)。
分享最佳实践清单
- 🔗链接和口令走不同渠道——链接走邮件,口令走电话或聊天工具,单独拿到任何一样都打不开;
- ⏳按需设置有效期与次数:默认 24 小时、默认只允许打开 1 次("一次打开 = 一个浏览器标签");需要连续多天阅读就给
--max-claims 5; - 🛑用完即吊销:
xerj share --revoke <handle>会使该分享铸造的所有 guest key 立即失效;--tunnel模式在 Ctrl-C 时自动吊销; - 🔍只分享该分享的索引:没有文档级权限,宁可少索引,不要多分享;
- 🌐想端到端加密就用自己的 TLS:
--public-url指向自有证书的反向代理,而不是 quick tunnel。
延伸阅读
- 完整威胁模型与命令参考:docs/SHARING.md
- 安全模型总览(含 guest 章节):docs/SECURITY_MODEL.md
- guest 路由白名单源码:engine/crates/xerj-api/src/authz.rs
- 分享记录、口令哈希与限流实现:engine/crates/xerj-api/src/share.rs
- CLI 与隧道管理器:engine/crates/xerj-server/src/share.rs
- guest 页面实现:xerj-ux/share/share.js
- 实机安全测试:engine/crates/xerj-api/tests/live/share_security_live.py
- 验证记录:docs/usecases/share-links/VERIFICATION.md
- 人工智能
- 搜索引擎
- 本地部署
- 后端
- MCP 服务
【免费下载链接】xerj
XERJ is the new way for AI to search data. Its autoindex capability activates agents to know your data without the token waste of grep and sed. One command indexes code, docs, logs and PDFs for search, RAG, security audits and agent memory, using 40x fewer tokens than grep. Elasticsearch compatible, so existing clients just work.
相关推荐
XERJ 分享链接来宾权限边界:一次链接 + 口令,来宾到底能碰到节点的什么
XERJ 分享链接来宾权限边界:一次链接 + 口令,来宾到底能碰到节点的什么 分享链接(share link)是 XERJ 用一条命令把「单个已索引语料」交给一
人工智能搜索引擎本地部署后端MCP 服务Codex-X 安全边界指南:能做什么、不能做什么,一份完整清单
Codex X 安全边界指南:能做什么、不能做什么,一份完整清单 Codex X 是一款面向 OpenAI Codex 桌面端与 Codex CLI 的可视化配
桌面应用开发者工具AI 应用屏幕级对话副驾刷屏:不改包、不接内部接口、绝不碰转账,Jev聊天助手凭什么敢这么设计
屏幕级对话副驾刷屏:不改包、不接内部接口、绝不碰转账,Jev聊天助手凭什么敢这么设计 2026年9月中旬,一个"不会说话"的AI模型在开发者社区刷屏:TypeS
AI 应用大模型交互助手RAG
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考