| 1 | package sandbox |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "encoding/json" |
| 6 | ) |
| 7 | |
| 8 | // EscapeRequest describes a one-shot request to rerun a shell command without |
| 9 | // the OS sandbox after the platform sandbox failed to start. |
| 10 | type EscapeRequest struct { |
| 11 | Command string |
| 12 | Args json.RawMessage |
| 13 | Reason string |
| 14 | } |
| 15 | |
| 16 | // EscapeApprover asks the user whether one command may run unconfined after the |
| 17 | // OS sandbox failed. Nil means fail closed. |
| 18 | type EscapeApprover interface { |
| 19 | ApproveSandboxEscape(ctx context.Context, req EscapeRequest) (allow bool, reason string, err error) |
| 20 | } |
| 21 | |
| 22 | // EscapeSessionChecker reports whether a sandbox escape has already been |
| 23 | // approved for the current session without prompting the user again. |
| 24 | type EscapeSessionChecker interface { |
| 25 | SandboxEscapeSessionAllowed(ctx context.Context, req EscapeRequest) bool |
| 26 | } |
| 27 | |
| 28 | type escapeApproverContextKey struct{} |
| 29 | |
| 30 | // WithEscapeApprover stamps an interactive sandbox-escape approver onto a tool |
| 31 | // execution context. |
| 32 | func WithEscapeApprover(ctx context.Context, approver EscapeApprover) context.Context { |
| 33 | if approver == nil { |
| 34 | return ctx |
| 35 | } |
| 36 | return context.WithValue(ctx, escapeApproverContextKey{}, approver) |
| 37 | } |
| 38 | |
| 39 | // EscapeApproverFrom returns the sandbox-escape approver carried by ctx. |
| 40 | func EscapeApproverFrom(ctx context.Context) (EscapeApprover, bool) { |
| 41 | if ctx == nil { |
| 42 | return nil, false |
| 43 | } |
| 44 | approver, ok := ctx.Value(escapeApproverContextKey{}).(EscapeApprover) |
| 45 | return approver, ok && approver != nil |
| 46 | } |
| 47 |