From 7d0f557811bc28d77faa6362cac373d3e9c06bde Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Fri, 25 Sep 2026 06:36:41 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=B0=E5=BD=95=20env-defaults.sh=20?= =?UTF-8?q?=E7=9A=84=E7=AC=AC=E4=BA=8C=E5=A4=84=E5=90=8C=E5=BD=A2=E5=81=87?= =?UTF-8?q?=E7=BB=BF=EF=BC=88=E5=B7=B2=E4=BF=AE=20eb5c4aa=EF=BC=89:=20179/?= =?UTF-8?q?196=20=E4=B8=A4=E5=A4=84"=E5=8F=AF=E5=86=99=E5=90=97"=E5=8F=AA?= =?UTF-8?q?=E7=9C=8B=E6=9D=83=E9=99=90=E4=BD=8D=EF=BC=8C=E8=80=8C=E5=90=8C?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20297=20=E8=A1=8C=E7=94=A8=E7=9A=84=E6=98=AF?= =?UTF-8?q?=E7=9C=9F=E5=86=99=E6=8E=A2=E9=92=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ★ 缺陷: [ -w /root ] 与 [ -w /opt/agentmail ] 都返 true,而真写全 Permission denied; 177 行原本就诊断对了("mkdir -p 会返成功 ⇒ 必须再单独判"),但"那个单独判"选错了层 ★ 后果撞在文件自己存在的理由上: HOME 空+uid=0 ⇒ /root 误判可用 ⇒ HOME=/root ⇒ ② 段 GOCACHE 用真写探针(297)失败 ⇒ 报「**GOCACHE** 不可写」而根因是 **HOME** ⇒ **误指对象** ⇒ 同一文件两套做法并存(一处真写一处看权限位),而错的那处更靠前 ★ 修法: 加 _am_can_write() 真写探针,179/196 一起改(196 的 else 是 exit 2 不是 fallback, 只改 196 会 exit 2 而不改判);WARN 括注不再报"按 uid 猜的原因" ★ ⚠️ WARN 前半句一字未动 —— 它是 pi env-guard.test.mjs:268 的 assert 锚; 我第一版改成"写不进去"实测把 pi 的测试弄红(16/17),已改回 ⇒ 17/17 绿 ⇒ 记法: 改文案前 grep 全仓谁匹配它;"锚"是别人的判据,不是我的措辞 ★ 变异测试: _am_can_write 恒真 ⇒ 被抓,且复现的正是那条误指 ✓ ★ 反空真: /tmp、工作区返真;/root、/opt、/nonexistent、空串返假 ⇒ 有区分力 ✓ ★ 边界: 生产未动;三处 source 者未改 --- docs/API.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docs/API.md b/docs/API.md index 731a287..cb59eeb 100644 --- a/docs/API.md +++ b/docs/API.md @@ -4785,3 +4785,48 @@ window.__AGENTMAIL_TOKEN__ = ''; // 省略则走 Cookie 而那个差异**不存在**(是我探针的假绿造出来的) ``` ## (E) 边界: 只读探针 + 三个**注定失败**的写入尝试(无一改到生产);仓库/生产未动 + +--- + +- ★★ **顺着我自己的假绿,在 `deploy/lib/env-defaults.sh` 里查到同一形状的第二处**(已修 `031848d`) + 这是"`[ -w ]` 查权限位、而拦截在另一层"那一条的**同一个错,长在我自己的 scope 里** + + ## (A) 缺陷:两处"可写吗"都只看权限位 + ``` + deploy/lib/env-defaults.sh:196 if mkdir -p "$_am_home" 2>/dev/null && [ -w "$_am_home" ]; then + deploy/lib/env-defaults.sh:179 ... [ ! -d "$_am_home" ] || [ ! -w "$_am_home" ]; then + 本机实测(同一台、同一 shell,uid=0): + [ -w /root ] ⇒ true / touch /root/x ⇒ **Permission denied** + [ -w /opt/agentmail ] ⇒ true ⇒ touch /opt/agentmail/x ⇒ **Permission denied** + ★ 注意 177 行**原本就写着** "mkdir -p 对已存在的不可写目录会返回成功,所以必须再单独判" —— + 诊断是对的,**但"那个单独判"选错了层**(`-w` 而不是真写) + ``` + ## (B) 后果正撞在文件自己存在的理由上 —— **误指对象** + ``` + HOME 空 + uid=0 ⇒ _am_home=/root ⇒ 179/196 判"可用" ⇒ HOME=/root 放行 + ⇒ ② 段取 $HOME/.cache/go-build 当 GOCACHE + ⇒ 那里用的是**真写探针**(297 行 `: > "$_am_gocache/.agentmail-probe"`)⇒ 失败 + ⇒ 报出「**GOCACHE**=/root/.cache/go-build 不可写」 + ⇒ 根因是 **HOME**,报出来的是 **GOCACHE** —— 而本文件的头号理由是"把环境问题说清楚", + 它却把一个环境问题**指到了另一个对象**上(实测可复现) + ⇒ ★ 同一文件里**两种做法并存**: 297 行真写、196 行看权限位 —— + "同一个问题两套判据"本身就是缺陷的形状(一处对一处错,而错的那处更靠前) + ``` + ## (C) 修法与验证 + ``` + 加 `_am_can_write()`(**真去写探针文件**,与 297 行同一办法),179/196 两处都用它。 + ★ **必须两处一起改**: 196 的 else 是 `exit 2`(不是 fallback)⇒ 只改 196 会让 /root + 直接 exit 2,而不是改判到 fallback。 + ★ WARN 括注从"(非 root / passwd 里没有可用目录)"改成"(已实测真写探针;uid=%s)" —— + 原括注是**按 uid 猜的原因**,而判据已不按 uid 判(uid=0 也会走到这里): + **不报没验过的原因**。 + ⚠️ 前半句 `按身份推出来的 HOME=%s 不可用` **一字未动** —— + 它是 `plugins/pi-mail-bridge/test/env-guard.test.mjs:268` 的 assert.match **锚**。 + 我第一版改成了"写不进去",**实测把 pi 的测试弄红(16/17)**,已改回 ⇒ 17/17 绿。 + ⇒ 记法: 改文案前先 grep 全仓**谁匹配这句话**;"锚"是别人的判据,不是我的措辞。 + ★ 变异测试: `_am_can_write` 改成恒真 ⇒ **被抓住**,且复现的正是上面那条误指 + (HOME 空时不再改判 ⇒ 直接报「GOCACHE 不可写」)✓ + ★ 反空真: 对 /tmp、工作区返真;对 /root、/opt/agentmail、/nonexistent、空串返假 + ⇒ 有区分力(非恒真、非恒红)✓ + ``` + ## (D) 边界: 只读探针 + 三次注定失败的写入尝试(无一改到生产);生产未动;三处 source 者未改