Files
AIclinicalresearch/docs/03-业务模块/SSA-智能统计分析/06-开发记录/SSA-Pro R 服务代码深度审查报告.md

98 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# **SSA-Pro R 服务代码深度审查报告**
**审查对象:** SSA-Pro R Service Source Code (v1.0)
**审查文件:** Dockerfile, plumber.R, data\_loader.R, guardrails.R, etc.
**审查时间:** 2026-02-18
**审查结论:** 🟡 **总体优秀,但存在阻断性缺失 (Blocker)**
## **1\. 🚨 阻断性问题 (Critical Issues)**
**这些问题会导致服务无法启动或无法下载数据,必须在联调前修复。**
### **1.1 data\_loader.R 中缺失 OSS 签名函数**
* **问题描述**:在 data\_loader.R 第 63 行调用了 generate\_oss\_signature(config, "GET", oss\_key),但我翻遍了上传的所有文件,**没有找到这个函数的定义**。
* **风险**:代码运行到下载 OSS 步骤时会直接报错 Error: could not find function "generate\_oss\_signature"。
* **修复建议**
1. **方案 A (推荐)**:在 utils/ 下新建 oss\_signer.R实现阿里云 OSS 的 HMAC-SHA1 签名逻辑(需要引入 digest 和 base64enc 包)。
2. **方案 B (替代)**:如果不想手写签名,可以使用系统调用 awscli (配置阿里云 endpoint) 或寻找现成的 R 包(如 aliyunr但需验证维护状态
### **1.2 plumber.R 的动态加载性能隐患**
* **问题描述**:在 plumber.R 的 POST /api/v1/skills/\<tool\_code\> 接口中,第 38 行使用了 source(tool\_file)。这意味着**每次请求都会重新从磁盘读取并解析 R 脚本**。
* **风险**
* **开发环境**:这是好事,支持热重载。
* **生产环境**:这是性能杀手。在高并发下,频繁的磁盘 I/O 和语法解析会显著增加延迟。
* **修复建议**
* 引入 DEV\_MODE 变量判断。
* **生产环境**:在服务启动时(第 13 行左右)预先加载所有 tools/ 下的脚本,或者使用 environment 缓存已加载的函数。
* **开发环境**:保持现有的动态 source 逻辑。
## **2\. 工程与安全隐患 (Engineering & Security Risks)**
### **2.1 Docker 容器的 Root 权限风险**
* **问题描述**Dockerfile 未指定用户,默认使用 root 运行 R 服务。
* **风险**:如果 R 代码中存在漏洞(如允许执行系统命令 system()),攻击者将获得容器的 Root 权限,可能逃逸或破坏文件系统。
* **修复建议**:在 Dockerfile 末尾添加非特权用户切换:
RUN useradd \-m appuser
USER appuser
### **2.2 路径遍历攻击 (Path Traversal)**
* **问题描述**plumber.R 第 33 行:
tool\_file \<- file.path("tools", paste0(tolower(gsub("ST\_", "", tool\_code)), ".R"))
虽然做了 gsub但如果 tool\_code 包含 ../ 等字符,仍可能尝试访问上层目录。
* **修复建议**:增加严格的白名单校验,或者校验 tool\_code 只能包含字母、数字和下划线。
if (\!grepl("^\[A-Z0-9\_\]+$", tool\_code)) {
return(list(status="error", message="Invalid tool code format"))
}
## **3\. 最佳实践点赞 (Highlights) ✅**
1. **依赖锁定 (renv.lock)**:使用了 renv 进行包管理,这是 R 工程化的基石,做得非常棒。
2. **护栏设计 (guardrails.R)**
* 包含了 LARGE\_SAMPLE\_THRESHOLD (5000) 的抽样逻辑,避免了大样本下 Shapiro 检验过敏的问题,非常专业的统计学处理。
* 接口设计清晰 (passed, action, reason)。
3. **结果格式化 (result\_formatter.R)**:统一处理了 P 值 \< 0.001 的显示,符合 APA 规范。
4. **环境隔离 (docker-compose.yml)**:正确使用了环境变量注入 OSS 配置,且区分了开发/生产环境。
## **4\. 优化代码清单 (Code Improvement Snippets)**
### **补全 OSS 签名逻辑 (utils/oss\_signer.R)**
*这部分逻辑比较复杂,我直接提供一个简版实现供参考:*
library(digest)
library(base64enc)
generate\_oss\_signature \<- function(config, verb, resource) {
date \<- format(Sys.time(), "%a, %d %b %Y %H:%M:%S GMT", tz="GMT")
content\_type \<- ""
content\_md5 \<- ""
canonicalized\_resource \<- paste0("/", config$bucket, "/", resource)
string\_to\_sign \<- paste(verb, content\_md5, content\_type, date, "", canonicalized\_resource, sep="\\n")
signature \<- base64encode(hmac(config$access\_key\_secret, string\_to\_sign, algo="sha1", raw=TRUE))
auth\_header \<- paste0("OSS ", config$access\_key\_id, ":", signature)
return(c("Authorization" \= auth\_header, "Date" \= date))
}
*注意:需要在 renv.lock 中补充 digest 包。*
## **5\. 总结**
这份代码作为 MVP 已经达到了 **85分** 的水平。
**接下来的行动指南:**
1. **必须做**:补全 generate\_oss\_signature 函数(或相关文件)。
2. **必须做**:在 renv 中添加 digest 依赖。
3. **建议做**:优化 plumber.R 的生产环境加载逻辑。
请将这份报告发给 R 开发工程师,让他们快速修正,然后就可以开始构建镜像了。