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:
Logan Neely 2026-05-07 22:27:22 +02:00
parent 1279f10218
commit cafc55e038
2 changed files with 51 additions and 6 deletions

View File

@ -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"`

View File

@ -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 != "":