背景
有个消费方(值班告警诊断 skill)在用 source-map-parser CLI 把 minified stack 映射回源码。目标是让它彻底脱离 Node、纯 shell(jq 拼 stack)+ CLI 完成。目前还差两块能力,仍被迫保留一层 Node 编排脚本来补:
- 跨进程磁盘缓存 + ETag——CLI 现在只有
map 里那个进程内 HashMap(单次调用内去重),load_map 是裸 ureq::get,无磁盘缓存、无条件请求。消费方场景是「同一 release 的 5MB+ .map 在多张工单反复出现」,每次重下代价大,故目前由 Node 侧 cached-fetch(磁盘 LRU + If-None-Match)兜着。
- 安全的 URL 规则求值——上游 APM 按项目返回一段 JS 规则(形如
originUrl.replace('/assets/','/sm/').replace('.js','.js.map'))把 JS URL 映射成 .map URL。CLI 的 --map-url-template 只做 {url} 字面替换,表达不了任意 .replace 链,所以消费方仍在 Node 里用 new Function(rule) eval(RCE 隐患)。
诉求
1. 磁盘缓存 + ETag(--map-url-template 拉取路径)
load_map 拉取远程 .map 时接入磁盘缓存:命中且有 ETag → 落盘;下次带 If-None-Match,304 直读盘。
- 缓存目录可配(env,如
SOURCE_MAP_PARSER_CACHE_DIR),容量 LRU(按 size,默认值可对齐现有 MCP 的 200MB)。
- 参考实现:
source-map-parser-mcp 的 cachingFetch / memoryCacheManager(把内存版落到磁盘即可)。
- 建议加
--no-cache 显式关闭。
2. 安全 URL 规则(替代 new Function)
二选一(或都做):
- 方案 A(推荐):新增
--map-url-replace <FROM> <TO>(可重复,按顺序 apply 到 JS URL 得 .map URL)。覆盖绝大多数 APM 规则(就是若干次字面/正则 replace),且完全无 eval。
source-map-parser map --stack - \
--map-url-replace '/assets/' '/sourcemaps/' \
--map-url-replace '.js' '.js.map'
- 方案 B:接受 APM 那段 rule 字符串,在 Rust 侧用受限求值器(只允许
originUrl + 链式 .replace(strOrRegex, str),AST 白名单,非通用 JS eval)跑,例如 --map-url-rule '<rule>'。这样消费方可直接把 APM 原样规则透传,CLI 安全求值,彻底消除 Node 侧 RCE。
收益
上述两条到位后,消费方可整体删掉 Node 编排层,改成 jq 拼 stack | source-map-parser map --map-url-replace ... / --map-url-rule ...,做到无 Node、无 node_modules、无 RCE。
参考
- 现状代码:
crates/cli/src/main.rs(load_map 约 324 行、进程内 cache 约 239 行、--map-url-template 约 305 行)。
- 消费方现在的临时形态(保留 Node 编排 + cached-fetch):见下游 agent-factory MR(sourcemap 解析改用原生 CLI)。
背景
有个消费方(值班告警诊断 skill)在用
source-map-parserCLI 把 minified stack 映射回源码。目标是让它彻底脱离 Node、纯 shell(jq 拼 stack)+ CLI 完成。目前还差两块能力,仍被迫保留一层 Node 编排脚本来补:map里那个进程内HashMap(单次调用内去重),load_map是裸ureq::get,无磁盘缓存、无条件请求。消费方场景是「同一 release 的 5MB+ .map 在多张工单反复出现」,每次重下代价大,故目前由 Node 侧cached-fetch(磁盘 LRU +If-None-Match)兜着。originUrl.replace('/assets/','/sm/').replace('.js','.js.map'))把 JS URL 映射成 .map URL。CLI 的--map-url-template只做{url}字面替换,表达不了任意.replace链,所以消费方仍在 Node 里用new Function(rule)eval(RCE 隐患)。诉求
1. 磁盘缓存 + ETag(
--map-url-template拉取路径)load_map拉取远程 .map 时接入磁盘缓存:命中且有ETag→ 落盘;下次带If-None-Match,304 直读盘。SOURCE_MAP_PARSER_CACHE_DIR),容量 LRU(按 size,默认值可对齐现有 MCP 的 200MB)。source-map-parser-mcp的cachingFetch/memoryCacheManager(把内存版落到磁盘即可)。--no-cache显式关闭。2. 安全 URL 规则(替代
new Function)二选一(或都做):
--map-url-replace <FROM> <TO>(可重复,按顺序 apply 到 JS URL 得 .map URL)。覆盖绝大多数 APM 规则(就是若干次字面/正则 replace),且完全无 eval。originUrl+ 链式.replace(strOrRegex, str),AST 白名单,非通用 JS eval)跑,例如--map-url-rule '<rule>'。这样消费方可直接把 APM 原样规则透传,CLI 安全求值,彻底消除 Node 侧 RCE。收益
上述两条到位后,消费方可整体删掉 Node 编排层,改成
jq 拼 stack | source-map-parser map --map-url-replace ... / --map-url-rule ...,做到无 Node、无 node_modules、无 RCE。参考
crates/cli/src/main.rs(load_map约 324 行、进程内cache约 239 行、--map-url-template约 305 行)。