diff --git a/CHANGELOG.md b/CHANGELOG.md index e1328690a7..21258f2169 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -466,6 +466,15 @@ This release closes that milestone with **301 merged pull requests**. ### Fixed +- **sandbox:** Medium-risk audit warnings no longer hide a failed shell exit from + subagent evidence. `SandboxAuditMiddleware` appended its warning after the + trailing `Exit Code: N` marker and rebuilt the `ToolMessage` from four fields, + so `_bash_evidence_status` could not find the marker and fell back to + `deerflow_tool_meta`, which reports `success`; a failed `sudo pytest -q` could + satisfy a `tests_passed` acceptance criterion. The warning is now inserted + before a trailing `Exit Code: N` or `Command exited with code N`, an output + that is only `Command exited with code N` is left unchanged, and the result + keeps `deerflow_tool_meta`, `artifact` and `id`. ([#6307]) - **persistence:** A second Gateway instance no longer fails startup with `TimeoutError` while another instance runs a PostgreSQL schema migration. The bootstrap advisory lock was taken with a blocking `pg_advisory_lock` on the @@ -7756,3 +7765,4 @@ with **180 merged pull requests** since the first 2.0 milestone tag. [#6282]: https://github.com/bytedance/deer-flow/pull/6282 [#6305]: https://github.com/bytedance/deer-flow/pull/6305 [#6306]: https://github.com/bytedance/deer-flow/pull/6306 +[#6307]: https://github.com/bytedance/deer-flow/pull/6307 diff --git a/CHANGELOG_zh.md b/CHANGELOG_zh.md index ec8b5bf691..9600d1dffb 100644 --- a/CHANGELOG_zh.md +++ b/CHANGELOG_zh.md @@ -423,6 +423,13 @@ ### 修复 +- **沙箱:** 中风险审计警告不再让子智能体证据丢失失败的 shell 退出码。 + `SandboxAuditMiddleware` 原先把警告追加在结尾的 `Exit Code: N` 标记之后,并只用 + 四个字段重建 `ToolMessage`,导致 `_bash_evidence_status` 找不到标记,退回到报告 + `success` 的 `deerflow_tool_meta`,失败的 `sudo pytest -q` 可能满足 `tests_passed` + 验收条件。现在警告插在结尾的 `Exit Code: N` 或 `Command exited with code N` + 之前,整段只有 `Command exited with code N` 的输出保持原样,结果保留 + `deerflow_tool_meta`、`artifact` 与 `id`。([#6307]) - **持久化:** 另一个实例正在执行 PostgreSQL 模式迁移时,第二个 Gateway 实例不再 因 `TimeoutError` 启动失败。引导期 advisory lock 此前在应用引擎上以阻塞的 `pg_advisory_lock` 获取,而该引擎的 asyncpg `database.command_timeout`(默认 @@ -6470,3 +6477,4 @@ DeerFlow 2.0 是围绕"超级智能体"框架的彻底重写,核心包含子 [#6282]: https://github.com/bytedance/deer-flow/pull/6282 [#6305]: https://github.com/bytedance/deer-flow/pull/6305 [#6306]: https://github.com/bytedance/deer-flow/pull/6306 +[#6307]: https://github.com/bytedance/deer-flow/pull/6307 diff --git a/backend/packages/harness/deerflow/agents/middlewares/AGENTS.md b/backend/packages/harness/deerflow/agents/middlewares/AGENTS.md index 3d056c0c9c..cfab9168c4 100644 --- a/backend/packages/harness/deerflow/agents/middlewares/AGENTS.md +++ b/backend/packages/harness/deerflow/agents/middlewares/AGENTS.md @@ -75,10 +75,10 @@ strict providers reject. `__authorization_outcome` key (so `build_run_config` strips caller-supplied forgeries). Consumers pop it; the publisher and the consumer share only that contract module. -12. **SandboxAuditMiddleware** - Audits sandboxed shell/file operations before tool execution; command classification is **defense-in-depth and audit, not a security boundary** (the sandbox is the isolation boundary). Command substitution is judged by *position*, not the presence of `$(`: **command position** (`$(curl url)`, `` `curl url` ``, the word after `|`/`&&`/`;`, an `eval`/`source` argument) executes fetched content and is blocked; **value position** (`x=$(curl url)`, `echo $(curl url)`, an argument, a `for` word list) only captures output and passes (#4611). So `_HIGH_RISK_COMMAND_POSITION_PATTERNS` is matched anchored against each sub-command from `_split_compound_command(split_pipes=True)`, never the whole string; pipe-spanning rules (`| sh`, `base64 -d | ...`) still use `_classify_command`'s whole-command Pass 1. `_COMMAND_POSITION_PREFIX` extends the anchor over leading assignments and exec wrappers (`FOO=1 $(curl url)`, `env`/`command`/`builtin`/`exec`/`nohup`/`time`/`sudo`/`doas`); its assignment branch requires whitespace before the substitution, which keeps `x=$(curl url)` in value position. Two contexts are deliberately **position-blind** (matched whole-command in Pass 1, since they execute their input anywhere, e.g. `xargs sh -c "$(curl url)"`): an `eval`/`source` argument, and an interpreter **code-string flag** — `-c` (shells, `python`), `-e` (`perl`/`ruby`/`node`), `-p` (`perl`/`node`), `-r` (`php`) — plus the here-string (`<<<`) reaching the same place via stdin. All three substitution spellings (`$(`, `<(`, `` ` ``) share one `_RISKY_SUBSTITUTION` opener. An unquoted newline splits like `;` (else `echo hi\n$(curl url)` evades the anchored rules). Heredoc bodies are data: `_split_compound_command` records headers (`<