Skip to content

[cosh-ng] checkpoint diff 在协议帧异常时泄漏内部 socket 路径与原始 io 错误 #1363

Description

@zhangtaibo

环境

  • 组件:cosh-ng
  • 版本:0.11.0
  • 测试环境:Linux x86_64 (Alinux 4)

复现步骤

  1. 执行 cosh-cli checkpoint diff --workspace <path> --from <bad-id> --to <bad-id>(使用不存在的 snapshot id)
  2. 观察 error.message 字段

预期

  • error.message 为友好措辞,不含内部 socket 路径或底层 Rust std::io 错误原文
  • error.code 准确反映"协议帧异常"或"daemon 返回异常响应"(而非 CheckpointDaemonUnavailable,因为 daemon 实际可达)

实际

  • error.code = CheckpointDaemonUnavailable
  • error.message = "I/O error while read response length: failed to fill whole buffer (<内部 socket 路径>)"
    • "failed to fill whole buffer" 是 Rust std::io 原始错误消息(UnexpectedEof)
    • 内部 socket 路径被直接拼进用户可见的 message

根因(源码定位)

crates/cosh-platform/src/checkpoint.rs classify_io_error()_ fallthrough 分支把 socket_path 与原始 io 错误拼进 message:

fn classify_io_error(e: std::io::Error, socket_path: &str, context: &str) -> CoshError {
    match e.kind() {
        std::io::ErrorKind::BrokenPipe => ...,
        std::io::ErrorKind::ConnectionReset => ...,
        std::io::ErrorKind::TimedOut => ...,
        std::io::ErrorKind::ConnectionRefused => ...,
        _ => CoshError::new(
            ErrorCode::CheckpointDaemonUnavailable,
            format!("I/O error while {}: {} ({})", context, e, socket_path),  // ← 泄漏
            "checkpoint",
        )
        .recoverable(true),
    }
}

read_exact 返回 UnexpectedEof("failed to fill whole buffer")时落入 _ 分支(未单独处理),把 socket_path 拼进 message。daemon 返回非帧格式响应(如错误字符串或提前关闭连接)即触发此路径。

影响

  • 内部 socket 路径泄漏到用户/Agent 可见输出,暴露运行时文件系统布局
  • 违反项目自身输出契约(不应在用户可见输出中暴露内部路径)
  • CheckpointDaemonUnavailable 分类不准 — daemon 实际可达,只是协议帧异常,Agent 据此可能误判为"重启 daemon 即可"
  • 错误消息低层、不友好,Agent 难以据此决策

复现稳定性

3/3 稳定复现

修复建议

  1. _ fallthrough 不在 message 里包含 socket_path(可放 error.details 字段,不进 message)
  2. UnexpectedEof 增加专门分支:映射为友好 message(如 "daemon response incomplete")与准确的 ErrorCode(如 CheckpointProtocolErrorUnknown)
  3. 区分"daemon 不可达"(ConnectionRefused/BrokenPipe)与"daemon 返回异常帧"(UnexpectedEof)

分类建议

PRODUCT_BUG

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions