execute: add Strict and Yolo server options
Strict rejects inline {code} steps, allowing only named {tool} steps.
Yolo skips the landrun sandbox entirely.
This commit is contained in:
parent
1279f10218
commit
cafc55e038
|
|
@ -187,6 +187,12 @@ func dispatchExecuteCode(ctx context.Context, e *Server, args json.RawMessage) (
|
|||
return "", fmt.Errorf("execute_code: at least one step is required")
|
||||
}
|
||||
|
||||
if e.Strict {
|
||||
if err := enforceStrict(stages); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
label := buildExecLabel(stages)
|
||||
if !e.allowed("execute_code", label) {
|
||||
return "", fmt.Errorf("execute_code: denied by user")
|
||||
|
|
@ -268,6 +274,22 @@ func buildExecLabel(stages []CodeStep) string {
|
|||
return sb.String()
|
||||
}
|
||||
|
||||
// enforceStrict rejects any step that uses inline code rather than a named tool.
|
||||
func enforceStrict(stages []CodeStep) error {
|
||||
for i, s := range stages {
|
||||
if len(s.Parallel) > 0 {
|
||||
if err := enforceStrict(s.Parallel); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if s.Tool == "" {
|
||||
return fmt.Errorf("execute_code: step %d rejected: inline code not allowed in strict mode", i)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func execCodeArgs(args json.RawMessage) (steps []CodeStep, timeout int, sandboxName string, err error) {
|
||||
var a struct {
|
||||
Steps []CodeStep `json:"steps"`
|
||||
|
|
|
|||
|
|
@ -43,6 +43,12 @@ type Server struct {
|
|||
// step dispatch. Set once at session init via SetLockDir; empty disables locking.
|
||||
lockDir string
|
||||
|
||||
// Strict rejects inline {code} steps; only {tool} steps are allowed.
|
||||
Strict bool
|
||||
|
||||
// Yolo skips the landrun sandbox for all execution.
|
||||
Yolo bool
|
||||
|
||||
// rate limiting state (per-Server)
|
||||
rateLimitMu sync.Mutex
|
||||
validationFailures int
|
||||
|
|
@ -50,10 +56,23 @@ type Server struct {
|
|||
blockedUntil time.Time
|
||||
}
|
||||
|
||||
// Option configures a Server.
|
||||
type Option func(*Server)
|
||||
|
||||
// WithStrict rejects inline {code} steps; only {tool} steps are allowed.
|
||||
func WithStrict() Option { return func(s *Server) { s.Strict = true } }
|
||||
|
||||
// WithYolo skips the landrun sandbox.
|
||||
func WithYolo() Option { return func(s *Server) { s.Yolo = true } }
|
||||
|
||||
// Decl returns a factory for an execute Server with the given working directory.
|
||||
func Decl(cwd string) func() tools.Server {
|
||||
func Decl(cwd string, opts ...Option) func() tools.Server {
|
||||
return func() tools.Server {
|
||||
return New(cwd)
|
||||
s := New(cwd)
|
||||
for _, o := range opts {
|
||||
o(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -334,11 +353,15 @@ func (e *Server) executeWithStdin(ctx context.Context, code, language string, ti
|
|||
default:
|
||||
return "", fmt.Errorf("unsupported language: %s (supported: bash, python3, perl, awk, sed, ed, jq, expect, bc, lua)", language)
|
||||
}
|
||||
wrapped, wrapErr := sandbox.WrapCommand(cfg, interpreter, workDir)
|
||||
if wrapErr != nil {
|
||||
return "", wrapErr
|
||||
if e.Yolo {
|
||||
cmd = exec.CommandContext(ctx, interpreter[0], interpreter[1:]...)
|
||||
} else {
|
||||
wrapped, wrapErr := sandbox.WrapCommand(cfg, interpreter, workDir)
|
||||
if wrapErr != nil {
|
||||
return "", wrapErr
|
||||
}
|
||||
cmd = exec.CommandContext(ctx, wrapped[0], wrapped[1:]...)
|
||||
}
|
||||
cmd = exec.CommandContext(ctx, wrapped[0], wrapped[1:]...)
|
||||
cmd.Dir = workDir
|
||||
switch {
|
||||
case codeStdin != "":
|
||||
|
|
|
|||
Reference in New Issue