Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

tracking: 外呼与输入校验面(4 项)—— 外部可控输入未被当作不可信数据

Đang mở
#191 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
12/100
Loại issue
Lỗi
Độ rõ ràng
Cần làm rõ
Mức độ hoạt động
Sôi nổi
Công nghệ
rust, shell
Lĩnh vực
networking, security

Hướng nghiên cứu

This is a tracking issue with no code of its own; the four child issues (#169 to #172) are the real work, and they must land in order. Start by reading src/tools/policy_domain/url_guard.rs around validate_url and is_private_ip, then src/tools/http_call.rs (encode_segment, build_url), src/tools/a2a.rs (the base interpolation and task_id check), and src/tools/install_skill.rs (slug and extract_zip). Done means the four cluster acceptance checks in the body pass, each with negative tests for the bypass cases.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

优先级 P1 · 依赖:无 · 类型:tracking(簇设计入口,不产出代码;子单全部落地后关闭)
记号:正文中的「不变量 #N」指 .dev/AGENTS.md 编号,不是 issue 编号;#150 这类才是 issue。本簇子单头部写 depends-on: #N 表示落地串行(同文件/同契约),不会与语义阻塞混淆。

基线 HEAD = 14bac15a(子单同基线)。本单来自一次全仓审计:先按根因归簇,再拆成可独立验收的子单。

共同根因

四条都是「外部可控输入没有被当成不可信数据」,集中在 url_guard 与两个外呼工具:

  1. SSRF 只查字面主机(#169):src/tools/policy_domain/url_guard.rs:58-145 对 Host::Domain 仅拦 localhost/*.localhost/metadata.google.internal 与 IP 字面写法,全仓无自定义 DNS resolver(连接期不校验),且 is_private_ip 漏 100.64/10、0/8(除 0.0.0.0)、::a.b.c.d、64:ff9b::/96。169.254.169.254.nip.io 这类名字直接放行(重定向绕过已由 Policy::none 关闭,剩下的就是 DNS 面)。
  2. 路径逃逸(#170):src/tools/http_call.rs:437-447 的 encode_segment 保留 .,整段 .. 经 build_url(:577-586)交给 Url::set_path 后被解析消解,且不校验最终 path 是否仍以运维 base path 为前缀 → 请求打到网关根路径并带着运维鉴权头。
  3. shell 注入(#171):validate_url 返回原始输入(url_guard.rs:121),a2a_call 把 base 直接插进单引号命令(src/tools/a2a.rs:272-292),只对 task_id 做了白名单(:389-409)→ 提前闭合引号的 curl|sh 可被注入。
  4. 技能安装缺完整性(#172):install_dir 放行 slug "."(src/tools/install_skill.rs:150-156)→ dest 变成共享根;extract_zip 剥第一层后可在 dest 内覆盖兄弟技能(:228-258);默认跟随重定向、read_to_end 无上限(:290-338、:350-363);slug 未编码即拼 URL(:454-497)。

子单与依赖

子单 依赖 范围
#169 无 自定义 reqwest Resolve:解析结果过 is_private_ip 再连;补齐私网/保留段
#170 depends-on: #169 拒绝 ./.. 参数;断言最终 path 以 base path 为前缀
#171 depends-on: #170 用规范化 Url;拒绝 ' " \ $ \ 空白`;优先 argv/env 传参
#172 depends-on: #171 slug 白名单 [A-Za-z0-9_-]+;redirect(none) + sha256 pin;entry/总量双上限

落地思路

  1. #169 不需要新依赖(不变量 #6 不受影响):本机 reqwest 0.12.28 已提供 ClientBuilder::dns_resolver 与 reqwest::dns::Resolve;把校验放在 resolver 里比放在 validate_url 里更难绕过(连接期生效)。
  2. 顺序按同文件串行:#169 与 #171 都动 url_guard.rs,#170/#171 都动 src/tools/ 与 URL 拼装,#172 依赖同一套出站校验约定。
  3. #170 加的是不变量式断言(final_url.path().starts_with(base_path)),比逐个过滤字符更可靠。
  4. 与 B 簇在 url_guard.rs(validate_url 被权限面复用)相邻;与 G 簇在 src/tools/ 相邻,按全局顺序错开。

簇级验收

  1. WebFetch/a2a 对 nip.io 形态、DNS rebinding 形态与 100.64.x.x 全部被拒;
  2. http_call 的 id=".." 构建失败;正常 id="42" 路径为 /{base}/42;
  3. a2a_call 收到含 '/空白/; 的 URL 时返回错误而非生成可执行命令;
  4. install_skill 拒 slug ".";含 ..//绝对路径/超限的 zip 被拒且无文件落盘。

边界

不含鉴权与租户身份(G 簇 #152、#146);不含 SKILL 内容来源的信任模型(#64/#76/#77 已定的 SkillSource 边界)。

实施顺序、PR 拆分与验收矩阵(补充 · 2026-10-10)

顺序(四单同域,串行):#169 → #170 → #171 → #172。

理由:#169 与 #171 都动 url_guard.rs;#170 与 #171 都动 URL 拼装;#172 依赖同一套"出站 URL 必须经校验"的约定。四单都不大,串行成本可接受。

跨簇重叠:url_guard.rs(validate_url)被权限面复用(B 簇 #153 只改工具名,不改 URL 逻辑,实际不冲突);src/tools/ 目录级重叠与 G 簇相邻。

PR 拆分:一子单一 PR。每个 PR 附"绕过尝试"的负向测试(本簇的价值就在于此)。

簇级验收 → 测试映射:见正文四条,落在 src/tools/policy_domain/url_guard.rs、src/tools/http_call.rs、src/tools/a2a.rs、src/tools/install_skill.rs 的单测中;#169 建议加一个 reqwest resolver 的单测(可用 Resolve trait 的纯函数部分)。

Ngôn ngữ chính
Rust
Star
4
Fork
0
Merge trung bình
5 giờ 32 phút
Pull request đã merge (30 ngày)
7

Chuẩn bị môi trường

  • Có Dockerfile hoặc tệp Docker Compose
  • Không có mẫu pull request
  • Không có hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của jeffkit/recursive

Tất cả issue của jeffkit/recursive

Issue tương tự

Thêm issue về Rust

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.