claude-mem 安全加固实战:watch.context.path 路径穿越防护、多用户端口隔离与 CI 注入审计
发布时间:2026/9/7 3:26:47来源:尧图网络
claude-mem 安全加固实战watch.context.path 路径穿越防护、多用户端口隔离与 CI 注入审计【免费下载链接】claude-memPersistent Context Across Sessions for Every Agent – Captures everything your agent does during sessions, compresses it with AI, and injects relevant context back into future sessions. Works with Claude Code, OpenClaw, Codex, Gemini, Hermes, Copilot, OpenCode More项目地址: https://gitcode.com/GitHub_Trending/cl/claude-mem本文围绕 claude-mem 仓库中的 Issue 分诊 Playbook TRIAGE-05-Security-Fixes.md分诊第 05 阶段高优先级安全修复展开。该阶段对应 Issue #1204、#1255、#1285、#1251 四个安全类问题涵盖 transcript watch 配置引发的任意文件写入、macOS 多用户环境下的端口共享数据串扰、GitHub Actions 工作流注入审查以及整体安全审计响应。读完本文你可以掌握该项目的安全威胁模型用户可控路径如何进入写文件调用链、worker 本地端口的多用户边界问题以及如何验证 CI 工作流不存在${{ github.event.* }}注入面并对照当前仓库源码确认各项修复的实际落地形态。一、阶段背景安全类 Issue 的分诊结论该阶段在 TRIAGE-05-Security-Fixes.md 中对四类问题给出了总体判定这也是全文的核心脉络一个真实漏洞通过watch.context.path实现的任意文件写入Issue #1204代码分析确认src/services/transcripts/processor.ts会将用户配置文件中的路径直接用于写操作且expandHomePath()只做~展开、不做边界校验一个设计层面的隐患多用户机器上的端口共享Issue #1255worker 绑定在127.0.0.1的固定端口同一台 macOS 上的多个本地用户会共享同一端口导致数据互相串扰两个需要审计而非改代码的项GitHub Actions 注入疑虑Issue #1285与安全审计请求Issue #1251代码分析确认 6 个工作流文件均无可利用的注入向量前置条件分诊阶段 01–04PR 合并、进程/资源稳定性、Hook 会话生命周期、worker 服务可靠性应先完成。其中两项代码修复#1204、#1255在 Playbook 中已标记完成分别新增 11 个和 9 个测试后两项是审计文档类工作。下面逐项展开并结合当前仓库源码核对修复的实际落地位置。二、任意文件写入watch.context.path 的边界校验#1204攻击面在哪里claude-mem 支持通过 transcript watch 配置监听各 Agent 的会话记录文件。watch 项中的context.mode agents表示每当转录内容更新就把压缩后的记忆上下文回写到watch.context.path指定的 AGENTS.md 类文件。这个路径来自用户主目录下的配置文件而处理入口是 processor.ts 中的updateContext()。问题链条很清晰配置加载函数 loadTranscriptWatchConfig() 读取并解析 JSON 配置原实现中context.path字段不做任何路径合法性校验路径展开函数 expandHomePath()src/services/transcripts/config.ts第 56–62 行只处理一个职责——把~前缀替换为用户主目录对../之类的穿越序列不做防御于是 processor 拿到watch.context.path后直接用于写入攻击者或误配置可以把上下文内容写到系统上任意可写位置。Playbook 中的修复设计Playbook 给出的修复要点是「在写入前做边界校验同时保持合理路径可用」const resolvedPath path.resolve(agentsPath)—— 先解析为绝对路径const homeDir os.homedir()—— 取用户主目录作为安全边界若解析后的路径不以homeDir开头记录警告并提前返回若解析后的路径仍含..段拒绝纵深防御同时在配置加载时loadTranscriptWatchConfig()提前拒绝任何解析到主目录之外的context.path明确约束校验不能过严~/.codex/AGENTS.md、~/project/AGENTS.md这类合法路径必须保持可用。当前源码中的落地形态对照当前仓库代码路径穿越防护实际落在两层第一层processor 侧的根白名单校验。在 processor.ts 的updateContext()第 358–370 行中路径先经过expandHomePath()展开再path.resolve()归一化然后检查是否落在允许的根目录之内const agentsPath expandHomePath(watch.context.path ?? ${cwd}/AGENTS.md); const resolvedAgentsPath path.resolve(agentsPath); const allowedRoots [path.resolve(cwd), path.resolve(DATA_DIR)]; const isPathSafe allowedRoots.some(root resolvedAgentsPath.startsWith(root path.sep) || resolvedAgentsPath root); if (!isPathSafe) { logger.warn(SECURITY, Rejected path traversal attempt in watch.context.path, { original: watch.context.path, resolved: resolvedAgentsPath, allowedRoots }); return; }从源码结构看这里的边界策略相比 Playbook 初稿的「仅限用户主目录」更进一步只允许写入当前会话工作目录或claude-mem 数据目录DATA_DIR之下攻击面比整个 home 目录更小且命中时以SECURITY分类打日志保留original/resolved/allowedRoots三个字段便于审计然后静默跳过而不是抛错中断 hook 链路。第二层写入函数自身的防御。agents-md-utils.ts 的writeAgentsMd()第 9–10 行在写入前拦截.git路径const resolvedPath resolve(agentsPath); if (resolvedPath.includes(/.git/) || resolvedPath.includes(\\.git\\) || resolvedPath.endsWith(/.git) || resolvedPath.endsWith(\\.git)) return;这层防护针对的是「把记忆上下文写进.git/内部从而污染版本库」这一特定风险覆盖 POSIX 与 Windows 两种分隔符形态。随后函数先写${agentsPath}.tmp临时文件再renameSync()原子替换第 24–28 行避免半截写入损坏 AGENTS.md——这是 Playbook 未展开、但对「写入类修复」很重要的配套细节。Playbook 同时要求不要过度收紧~/.codex/AGENTS.md等路径必须继续合法。这一点在 config.ts 的isNativeHookBackedCodexWatch()第 17–25 行中得到印证——Codex 的~/.codex/sessions/**/*.jsonlwatch 是产品支持的规范配置白名单设计必须与之兼容。三、多用户 macOS 下的跨账户数据泄漏按 UID 派生端口#1255问题本质worker 是一个常驻本地 HTTP 服务监听127.0.0.1:端口。Playbook 指出的问题在于原始默认端口是固定值37777。在共享一台 macOS 机器多个本地用户账户的场景下两个用户各自安装 claude-mem 后两个 worker 会争抢/共享同一个端口——后启动的一方要么失败要么连上别人的worker读取到他人的会话记忆数据造成跨账户数据串扰。Playbook 的修复方案Playbook 给出的方案是按用户 UID 派生端口核心规则获取当前用户 UIDprocess.getuid()Unix或os.userInfo().uid跨平台计算端口37777 (uid % 1000)让每个用户落在 1000 个端口的区间内互不冲突仅当用户没有显式设置CLAUDE_MEM_WORKER_PORT时才应用派生逻辑——环境变量优先级始终最高文档注释中的37777需要同步更新但设置默认值本身保持37777作为基座派生逻辑单独一层Playbook 还评估了替代方案把 TCP 监听换成 Unix domain socket~/.claude-mem/worker.sock。结论是 UDS 更安全但可能破坏 Windows 兼容性因此最终选择 per-user 端口方案。当前源码中的落地形态当前代码中按 UID 派生端口的逻辑直接体现在设置默认值层。SettingsDefaultsManager.ts第 137 行CLAUDE_MEM_WORKER_PORT: String(37700 ((process.getuid?.() ?? 77) % 100)),从源码结构看这一行与 Playbook 方案在思路上完全一致——默认端口不再是纯常量而是由 UID 派生的每用户值process.getuid?.()带 fallback77兼容没有getuid的平台如 Windows模 100 把偏移收敛到 100 个端口的窗口内。基座值在演进中从37777调整为37700区间但「UID 派生 用户可覆盖」的契约保持不变实际取端口值的是 worker-utils.ts 中的getWorkerPort()第 127–135 行它从settings.json读取CLAUDE_MEM_WORKER_PORT并缓存——用户显式设置的端口写入 settings 的永远优先于派生默认值满足 Playbook 第 3 条的「显式覆盖」约束所有 hook、MCP server、CLI 都通过buildWorkerUrl()第 172–174 行统一拼http://host:port因此端口派生只需要在默认值这一处生效全链路自动跟随这正是 Playbook 强调「单一派生点」的价值。此外CLAUDE_MEM_QUEUE_REDIS_PREFIX默认值第 227 行同样内嵌了端口/UID 派生表达式说明该隔离策略被推广到了队列命名空间进一步避免多用户共享 Redis 时的前缀冲突。四、GitHub Actions 注入疑虑的审计结论#1285Playbook 对#1285的处理方式是审计后关闭而非改代码。其结论是逐行审查所有工作流文件后确认不存在可利用的注入向量具体证据链如下——convert-feature-requests.yml使用actions/github-scriptv8通过 GitHub API 调用完成任务不经过 shell 插值claude.yml使用 Anthropic 官方claude-code-action当前仓库 .github/workflows/claude.yml 第 35 行为anthropics/claude-code-actionv1npm-publish.yml走标准 npm 发布流程无不可信输入参与deploy-install-scripts.yml只使用硬编码路径summary.yml引用github.event.issue.number这是 GitHub API 返回的可信数值型字段。对照当前仓库的.github/workflows/目录工作流集合已扩展为 8 个文件ci.yml、claude.yml、close-tracked-issues.yml、convert-feature-requests.yml、deploy-install-scripts.yml、npm-publish.yml、summary.yml、windows.yml新增文件延续了同样的安全模式全仓库范围内 greprun:块没有任何一处直接把${{ github.event.* }}拼进 shell 命令summary.yml 的正确姿势是把事件值放进环境变量再交给脚本消费run: | ... env 中: ISSUE_NUMBER: ${{ github.event.issue.number }}github.event.issue.number是数值类型且经 env 通道传递而非字符串插值进 shell两条防线叠加后不构成注入面。Playbook 给出的关闭评论模板也值得保留作为方法论参考Audited all 6 GitHub Actions workflows. No${{ github.event.* }}values are interpolated into shell run: commands. convert-feature-requests.yml uses actions/github-script with API calls. All workflows follow secure patterns. Closing as not-a-vulnerability.这套审计方法可以泛化判断 CI 是否可被 issue/PR 标题描述注入核心是检查run:步骤里的表达式插值以及外部输入走的是 env、API 参数还是 shell 字符串拼接。五、安全审计响应已确认安全的模式与遗留考量#1251#1251 是一次综合性审计请求Playbook 要求产出一份安全审计响应文档把「当前安全姿态」固化成可复查的记录。其中列出的已确认安全模式均可在当前源码中逐一核实1. Worker 只绑定 localhost管理端点有 requireLocalhost 中间件worker 服务通过server.listen(port, host)启动worker-service.ts 第 420 行host 默认来自CLAUDE_MEM_WORKER_HOST设置。管理端点由 middleware.ts 的requireLocalhost()第 64 行起守卫只放行127.0.0.1、::ffff:127.0.0.1、localhost三类回环来源其余直接返回「Admin endpoints are only accessible from localhost」并以SECURITY分类记录拒绝日志export function requireLocalhost(req: Request, res: Response, next: NextFunction): void { ... clientIp 127.0.0.1 || clientIp ::ffff:127.0.0.1 || clientIp localhost;2. CORS 仅限 localhost 源同一中间件文件第 47 行CORS 校验只接受http://localhost:与http://127.0.0.1:前缀的 Origin防止本机其他浏览上下文跨源读取 worker API。3. 路径边界校验与设置文件合并策略上文第二节的startsWith白名单校验属于第 3 类。此外设置加载采用merge-with-defaults模式SettingsDefaultsManager.ts 把用户settings.json与内置默认值合并意味着缺失或非法的设置项会落回安全默认值如上文第 2 节的端口派生默认值而不是让服务带着未定义行为启动。4. 遗留考量本地文件权限Playbook 还列出了两项尚未强制、但应落实的加固项~/.claude-mem/settings.json的文件权限应设为 user-only0600数据库文件~/.claude-mem/claude-mem.db应同为 user-only。这两项属于操作系统层权限卫生配合「worker 只监听回环 按 UID 派生端口」的网络层隔离构成完整的本地数据边界。作为更宏观的背景仓库另有两份安全文档可作为延伸阅读docs/security.md 说明 server beta 端默认启用 API-key 认证密钥以cmem_为前缀、仅存储 SHA-256 哈希、CLAUDE_MEM_AUTH_MODElocal-dev回环豁免仅在显式双开关下生效且不得暴露在公网SECURITY.md 则是漏洞报告的正式入口。本阶段#1251关注的本地多用户边界与 server 端认证边界互为补充共同覆盖 claude-mem 的两类部署形态。六、验证方式与回归要求Playbook 对该阶段设定的验收标准是回归性的可直接复现运行npm test—— 全部测试必须通过其中安全修复配套新增 11 个路径校验测试与 9 个端口派生测试仓库测试基线见 tests/ 目录下的tests/worker/、tests/shared/等子目录运行npm run build-and-sync—— 构建产物与同步链路正常。从仓库结构看相关行为约束散落在多个测试簇中worker 端口/健康检查相关契约见 tests/shared/worker-spawn-gate.test.ts 与 tests/services/worker-spawner.test.ts中间件与端口绑定相关断言集中在 tests/infrastructure/ 与 tests/worker/http/ 目录。修改writeAgentsMd()、getWorkerPort()或requireLocalhost()等任一安全关键点时都应把这两组测试作为回归门槛。小结TRIAGE-05 阶段的四条线勾勒出 claude-mem 本地端的安全模型用户可控输入watch 配置路径必须在写入边界做白名单校验——当前实现收敛到「cwd DATA_DIR 双根白名单 .git路径拦截 原子写」三层本地回环服务不是天然安全的——多用户共享主机时固定端口会造成跨账户数据串扰按 UID 派生端口并把显式覆盖权交给用户是低成本的隔离手段CI 审计以「输入是否进 shell」为判定标准——env 通道传递可信数值字段、github-script 走 API 调用构成无注入面的工作流范式最后以 requireLocalhost、CORS 同源限制、merge-with-defaults 等已确认模式加上本地文件 0600 权限卫生形成一份可复查的安全审计记录。这四类做法对任何「常驻本地服务 用户配置文件 CI 自动化」形态的开发者工具都有直接参考价值。【免费下载链接】claude-memPersistent Context Across Sessions for Every Agent – Captures everything your agent does during sessions, compresses it with AI, and injects relevant context back into future sessions. Works with Claude Code, OpenClaw, Codex, Gemini, Hermes, Copilot, OpenCode More项目地址: https://gitcode.com/GitHub_Trending/cl/claude-mem创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网