Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

tracking: 安全面闭环——已落地机制的绕过(4 项)

Aperta
#192 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
8/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
docker, linux, rust
Ambito
backend, security

Direzione di ricerca

This is a tracking issue for four sandbox and auth bypasses; no code is to be written here. Start from the sub-issues it links (#150, #152, #155, #167) and their cited files, such as src/tools/transport_layer/transport.rs and src/tools/dispatch.rs. Each sub-issue needs its own design and PR, and the cross-cluster file overlaps need coordination first.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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

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

共同根因

这四条的共同点是:机制已经落地,但能被绕过,或者声明与执行面不一致——比「功能缺失」更危险,因为运维会以为它生效了。

  1. 凭据面(#150):#89 的清洗只作用于子进程的 env 块(src/tools/transport_layer/transport.rs:803-810 的 scrub_child_env),而 exec_shell 用 Command::new("/bin/sh") 由服务进程直接 spawn(:897-925),shell 的 $PPID 就是 recursive 本身;服务进程自己的环境没有任何清理(非测试代码里 remove_var/prctl/PR_SET_DUMPABLE 零命中),于是 cat /proc/$PPID/environ 就能拿走 #89 明确要拦下的全部 key。注意:remove_var 修不了这个(glibc unsetenv 不改 execve 时的原始副本),必须靠 PR_SET_DUMPABLE=0 或干净环境 re-exec。
  2. 沙箱面(#155):resolve_within_any 只对已存在路径做 canonicalize 复查(src/tools/dispatch.rs:345-374),不存在的路径走词法 starts_with 并原样返回;WriteFile(src/tools/execution/fs.rs:567、648-702)与 EditTool(src/tools/execution/edit.rs:462)不做祖先 canonicalize → 工作区里一个 docs -> /外部 的链接即可写出沙箱。我已实测:同一条链接,写已存在文件被拒、写新文件被放行。
  3. 归属面(#152):#85 给 /sessions/* 建了归属校验(src/http/auth.rs:80-88 may_access_session),但 agui_run(src/http/handlers.rs:2581-2584)与 agui_cancel(:2902-2905)不取身份,线程键只是 blake3(threadId)(src/agui_session.rs:60-63);#147 落地后 load_thread_seed 会把 A 的完整历史播种进 B 的 run(src/http/agui.rs:730),取消也按原始 threadId 索引(handlers.rs:2906-2910)。
  4. 隔离声明面(#167):DockerToolSetProvider 在 Docker 不可用时只 warn 并保留宿主 Bash(src/tools/transport_layer/docker_provider.rs:79-83),sandbox_mode() 仍返回 Container(:88-90);遗留 docker_sandbox.rs 的容器用默认网络、root、无 cap_drop(:42-83),超时不杀 exec(:123-133),Drop 无条件 tokio::spawn(:141-155)。

子单与依赖

子单 依赖 范围
#150 无 启动后 PR_SET_DUMPABLE=0(或干净环境 re-exec)+不再把凭据留在进程环境;补 cat /proc/$PPID/environ 回归
#167 depends-on: #150 Docker 不可用即 fail-closed(或显著降级标志);遗留实现复用 secure_host_config、超时真杀、Drop 用 try_current
#152 无 agui_run/agui_cancel 取 AuthIdentity;线程元数据记 owner/tenant;active_runs 用命名空间化键
#155 无 不存在路径取最长已存在祖先 canonicalize 后复查;返回 canonical 路径;补 O_NOFOLLOW/openat 方向

落地思路

  1. #150 的修法要选对:remove_var 只是减少泄漏面,/proc/pid/environ 仍是 execve 时的副本;主修复是 Linux 启动即 prctl(PR_SET_DUMPABLE, 0)(同 uid 子进程读不到),或启动时用干净环境 re-exec。验收必须在子进程内读 /proc/$PPID/environ,不能只断言 Command::env。
  2. #155 返回 canonical 路径(而非原 abs_joined),缩短 check→write 的 TOCTOU 窗口;单测要覆盖「不存在的新文件」与「已存在的文件」两种,因为现有 tests/invariants/sandbox.rs:71 只覆盖「链接本身就是目标」。
  3. #152 与 #85 的语义保持一致:admin 仍可访问,其余按 (subject, tenant) 严格相等;agui_active_runs 的键必须与线程键同源,否则改名后取消会失效。
  4. #167 首选 fail-closed:宁可不提供 Bash,也不要「报告 Container 却跑在宿主」。
  5. 与 C 簇在 transport.rs、run_background.rs 重叠(C 的 #165/#177 也在 kill/环境路径上),与 B 簇在 handlers.rs 重叠 —— 按全局顺序错开。

簇级验收

  1. 子进程经 RunShell 执行 cat /proc/$PPID/environ,输出不含任一敏感变量名/值;
  2. root/docs -> /tmp/outside 时,Write docs/new.txt(不存在)与 docs/exists.txt(存在)都被拒,沙箱外无文件产生;
  3. 两个不同 subject 的凭据下,B 访问 A 的 threadId(/agui 与 /agui/{id}/cancel)得 403,A 的 transcript.jsonl 未被追加;
  4. Docker 不可用时构建结果不是「宿主 Bash + Container 报告」。

边界

不含默认档多租户数据面互通(#86)、不含 HTTP 侧人审闭环(#88)、不含权限判定绕过(B 簇)——本簇只收「已有机制被绕过」与「声明与执行面不一致」。

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

波 子单 理由
W1 #150 凭据面影响面最大(默认档即中招),且它要动 transport.rs 的启动/执行路径
W2 #167 同目录(transport_layer/),且 fail-closed 的判断要靠 #150 之后的环境模型稳定下来
并行 #152、#155 分别只动 http/handlers.rs+agui* 与 tools/dispatch.rs,互不冲突,可与上面并行

跨簇文件重叠(必须错开,不能同时派工)

文件 本簇子单 另一簇子单
src/tools/transport_layer/transport.rs #150(启动期加固 + exec_shell 环境) C 簇 #165(process_group 在同一个 exec_shell 里)
src/tasks/run_background.rs #150(宿主档同父进程的证据点) C 簇 #164/#177
src/http/handlers.rs #152(agui_run/agui_cancel) B 簇 #151/#154/#182(同一文件的权限路径)

PR 拆分:一子单一 PR。#150 的 PR 必须先于 C 簇 #165(两者都在 exec_shell 里改 spawn 前的设置,先合 #150 可避免 #165 之后 rebase 冲突)。

簇级验收 → 测试映射

验收 落点
① cat /proc/$PPID/environ 不含敏感变量 tests/issue89_parent_environ.rs(#[cfg(target_os = "linux")],测试进程内先调 harden_process())
② 链接目录写新文件/已存在文件都被拒 tests/invariants/sandbox.rs 新增两例(现有 :71 只覆盖"链接即目标")
③ B 访问 A 的 threadId 得 403 且 A 的 jsonl 未变 src/http/handlers.rs 的 #[cfg(test)] 或 tests/ 新增 HTTP 级用例(两个不同 AuthIdentity)
④ Docker 不可用时不出现"宿主 Bash + Container 报告" src/tools/transport_layer/docker_provider.rs 单测(注入失败的 docker 路径)

共同陷阱

  1. 三处"未归属/未配置"的语义必须与既有实现一致:#85 的规则是"没有归属信息的会话只有 admin 可达"(cold_load.rs:232-236),不要发明第二套规则。
  2. 单用户部署(未启用 auth)不能被打坏:Extension<AuthIdentity> 在 auth 中间件关闭时不存在,#152 必须把"取不到身份"当作"无归属模型、沿用旧行为",而不是 403。
  3. 本簇全部是"机制已存在但被绕过",因此每个 PR 都要包含原始机制仍然生效的对照断言(避免修 A 绕过时把 B 路径关掉)。
Lingua principale
Rust
Stelle
4
Fork
0
Merge medio
5h 32m
PR unite (30g)
7

Preparare l'ambiente

  • Include un Dockerfile o un file Docker Compose
  • Nessun modello di pull request
  • Nessuna guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di jeffkit/recursive

Tutte le issue di jeffkit/recursive

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.