feat(ssa): finalize strict stepwise agent execution flow
Align Agent mode to strict stepwise generation and execution, add deterministic and safety hardening, and sync deployment/module documentation for Phase 5A.5/5B/5C rollout. - implement strict stepwise execution path and dependency short-circuiting - persist step-level errors/results and stream step_* progress events - add agent plan params patch route and schema/migration support - improve R sanitizer/security checks and step result rendering in workspace - update SSA module guide and deployment change checklist Made-with: Cursor
This commit is contained in:
@@ -221,9 +221,10 @@ function(req) {
|
||||
|
||||
message(glue::glue("[ExecuteCode] session={session_id}, code_length={nchar(code)}, timeout={timeout_sec}s"))
|
||||
|
||||
# ── AST 语法预检:parse() 先于 eval(),快速捕获语法错误 ──
|
||||
# ── AST + 安全双层预检:语法检查 + 危险调用拦截 ──
|
||||
parsed_code <- NULL
|
||||
ast_check <- tryCatch({
|
||||
parse(text = code)
|
||||
parsed_code <<- parse(text = code)
|
||||
NULL
|
||||
}, error = function(e) {
|
||||
e$message
|
||||
@@ -252,8 +253,32 @@ function(req) {
|
||||
duration_ms = 0
|
||||
))
|
||||
}
|
||||
|
||||
# 安全预检(静态扫描,MVP)
|
||||
# 注:为减少误报,先粗略移除注释行再扫描
|
||||
code_for_scan <- gsub("(?m)^\\s*#.*$", "", code, perl = TRUE)
|
||||
forbidden_pattern <- "(^|[^[:alnum:]_\\.])((base::)?system|(base::)?eval|(base::)?parse|(base::)?source|file\\.remove|setwd|download\\.file|readLines|writeLines)\\s*\\("
|
||||
security_hit <- regexpr(forbidden_pattern, code_for_scan, perl = TRUE, ignore.case = TRUE)
|
||||
if (security_hit[1] != -1) {
|
||||
hit_text <- regmatches(code_for_scan, security_hit)[1]
|
||||
return(list(
|
||||
status = "error",
|
||||
error_code = "E_SECURITY",
|
||||
error_type = "security",
|
||||
message = paste0("Security Violation: Detected forbidden function call: ", hit_text),
|
||||
user_hint = "代码包含高风险函数调用(如 system/eval/source/file.remove/setwd),已被系统拦截",
|
||||
console_output = list(),
|
||||
duration_ms = 0
|
||||
))
|
||||
}
|
||||
|
||||
sandbox_env <- new.env(parent = globalenv())
|
||||
# 运行时保护:即使静态扫描漏检,也在沙箱层阻断关键高风险调用
|
||||
sandbox_env$system <- function(...) stop("Security Violation: function 'system' is forbidden.")
|
||||
sandbox_env$eval <- function(...) stop("Security Violation: function 'eval' is forbidden.")
|
||||
sandbox_env$source <- function(...) stop("Security Violation: function 'source' is forbidden.")
|
||||
sandbox_env$setwd <- function(...) stop("Security Violation: function 'setwd' is forbidden.")
|
||||
sandbox_env$file.remove <- function(...) stop("Security Violation: function 'file.remove' is forbidden.")
|
||||
|
||||
if (!is.null(session_id) && nchar(session_id) > 0) {
|
||||
sandbox_env$SESSION_ID <- session_id
|
||||
@@ -269,7 +294,7 @@ function(req) {
|
||||
{
|
||||
captured_output <- utils::capture.output({
|
||||
result <- withCallingHandlers(
|
||||
eval(parse(text = code), envir = sandbox_env),
|
||||
eval(parsed_code, envir = sandbox_env),
|
||||
warning = function(w) {
|
||||
collected_warnings[[length(collected_warnings) + 1]] <<- w$message
|
||||
invokeRestart("muffleWarning")
|
||||
|
||||
Reference in New Issue
Block a user