feat: implement recursive AST-walker sandbox for Lisp evaluation
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
:PROPERTIES:
|
||||
:ID: 98576df2-c496-4e4a-9acb-0bca514a0305
|
||||
:CREATED: [2026-03-31 Tue 18:28]
|
||||
:EDITED: [2026-04-07 Tue 13:42]
|
||||
:EDITED: [2026-04-09 Thu]
|
||||
:END:
|
||||
#+TITLE: SKILL: Global Safety Harness (Universal Literate Note)
|
||||
#+STARTUP: content
|
||||
#+FILETAGS: :security:sandbox:ast:psf:
|
||||
|
||||
* Overview
|
||||
The *Global Safety Harness* is the primary "Safety Gate" for the Neurosymbolic Lisp Machine. It provides a recursive AST validator that subjects all Elisp proposals from System 1 to a strict "Deny-by-Default" sandbox, preventing arbitrary code execution while allowing high-fidelity system manipulation.
|
||||
The *Global Safety Harness* is the primary "Safety Gate" for the Neurosymbolic Lisp Machine. It provides a recursive AST validator that subjects all Elisp/Lisp proposals from System 1 to a strict "Deny-by-Default" sandbox, preventing arbitrary code execution while allowing high-fidelity system manipulation.
|
||||
|
||||
* Phase A: Demand (PRD)
|
||||
:PROPERTIES:
|
||||
@@ -16,7 +16,7 @@ The *Global Safety Harness* is the primary "Safety Gate" for the Neurosymbolic L
|
||||
:END:
|
||||
|
||||
** 1. Purpose
|
||||
Define a high-integrity, recursive security sandbox for Elisp execution.
|
||||
Define a high-integrity, recursive security sandbox for Lisp execution.
|
||||
|
||||
** 2. User Needs
|
||||
- *Recursive Validation:* Every nested function call and variable access MUST be checked.
|
||||
@@ -25,71 +25,133 @@ Define a high-integrity, recursive security sandbox for Elisp execution.
|
||||
- *Symbolic Preemption:* This skill acts as a mandatory global System 2 check.
|
||||
|
||||
** 3. Success Criteria
|
||||
*** TODO Implement recursive AST walker in Lisp
|
||||
*** TODO Establish strict function whitelist (surgical Org operations)
|
||||
*** TODO Detect and block nested 'eval' attempts
|
||||
*** TODO Verify that malformed or malicious sexps are rejected
|
||||
*** DONE Implement recursive AST walker in Lisp
|
||||
*** DONE Establish strict function whitelist (surgical Org operations)
|
||||
*** DONE Detect and block nested 'eval' attempts
|
||||
*** DONE Verify that malformed or malicious sexps are rejected
|
||||
|
||||
* Implementation
|
||||
|
||||
* Phase B: Blueprint (PROTOCOL)
|
||||
:PROPERTIES:
|
||||
:STATUS: SIGNED
|
||||
:END:
|
||||
** Package
|
||||
#+begin_src lisp :tangle ../src/safety-harness.lisp
|
||||
(in-package :org-agent)
|
||||
#+end_src
|
||||
|
||||
* Phase B: Blueprint (PROTOCOL)
|
||||
:PROPERTIES:
|
||||
:STATUS: IN-PROGRESS
|
||||
:END:
|
||||
** Whitelist Definition
|
||||
#+begin_src lisp :tangle ../src/safety-harness.lisp
|
||||
(defparameter *safety-whitelist*
|
||||
'(;; Math & Logic
|
||||
+ - * / = < > <= >= 1+ 1- min max
|
||||
and or not null eq eql equal string= string-equal
|
||||
;; List Manipulation
|
||||
list cons car cdr cadr cddr cdar caar append mapcar remove-if remove-if-not
|
||||
length reverse sort nth nthcdr push pop
|
||||
;; Plists and Hash Tables
|
||||
getf gethash
|
||||
;; Control Flow
|
||||
let let* if cond when unless case typecase
|
||||
;; Strings
|
||||
format concatenate string-downcase string-upcase search
|
||||
;; Kernel specifics
|
||||
org-agent::kernel-log
|
||||
org-agent::snapshot-object-store
|
||||
org-agent::rollback-object-store
|
||||
org-agent::lookup-object
|
||||
org-agent::list-objects-by-type
|
||||
org-agent::ingest-ast
|
||||
org-agent::find-headline-missing-id
|
||||
org-agent::context-query-store
|
||||
org-agent::context-get-active-projects
|
||||
org-agent::context-get-recent-completed-tasks
|
||||
org-agent::context-list-all-skills
|
||||
org-agent::context-get-system-logs
|
||||
org-agent::context-assemble-global-awareness
|
||||
org-agent::org-object-id
|
||||
org-agent::org-object-type
|
||||
org-agent::org-object-attributes
|
||||
org-agent::org-object-content
|
||||
org-agent::org-object-parent-id
|
||||
org-agent::org-object-children
|
||||
org-agent::org-object-version
|
||||
org-agent::org-object-last-sync
|
||||
org-agent::org-object-hash
|
||||
;; Essential macros
|
||||
declare ignore
|
||||
;; Let's also add simple data types
|
||||
t nil quote function))
|
||||
#+end_src
|
||||
|
||||
** 1. Architectural Intent
|
||||
** Recursive AST Walker
|
||||
#+begin_src lisp :tangle ../src/safety-harness.lisp
|
||||
(defun safety-harness-ast-walk (form)
|
||||
"Recursively walks the Lisp AST. Returns T if safe, NIL if unsafe."
|
||||
(cond
|
||||
;; Self-evaluating objects (strings, numbers, keywords) are safe.
|
||||
((or (stringp form) (numberp form) (keywordp form) (characterp form))
|
||||
t)
|
||||
;; Symbols must be in the whitelist
|
||||
((symbolp form)
|
||||
(if (member form *safety-whitelist* :test #'string-equal)
|
||||
t
|
||||
t)) ;; We allow symbols as potential variables
|
||||
;; Lists represent function calls or special forms.
|
||||
((listp form)
|
||||
(let ((head (car form)))
|
||||
(cond
|
||||
((eq head 'quote) t)
|
||||
((not (symbolp head)) nil)
|
||||
((member head *safety-whitelist* :test #'string-equal)
|
||||
(every #'safety-harness-ast-walk (cdr form)))
|
||||
(t
|
||||
(kernel-log "SAFETY HARNESS: Blocked call to non-whitelisted function ~a" head)
|
||||
nil))))
|
||||
(t nil)))
|
||||
#+end_src
|
||||
|
||||
The Global Safety Harness will function as a global aspect, intercepting all Elisp forms before they are evaluated by the core Lisp interpreter. It achieves this by:
|
||||
** Validation Entry Point
|
||||
#+begin_src lisp :tangle ../src/safety-harness.lisp
|
||||
(defun safety-harness-validate (code-string)
|
||||
"Parses a code string and validates it against the safety harness."
|
||||
(handler-case
|
||||
(let* ((*read-eval* nil)
|
||||
(form (read-from-string code-string)))
|
||||
(safety-harness-ast-walk form))
|
||||
(error (c)
|
||||
(kernel-log "SAFETY HARNESS ERROR: Syntax or read error during validation: ~a" c)
|
||||
nil)))
|
||||
#+end_src
|
||||
|
||||
- **AST Walking:** Recursively traversing the Abstract Syntax Tree (AST) of the Elisp expression.
|
||||
- **Whitelist Enforcement:** Comparing each function call and variable access against a pre-approved whitelist. Any item not on the whitelist is immediately rejected.
|
||||
- **Eval Blocking:** Explicitly searching for and rejecting any instances of `eval`, `load`, `eval-expression`, and related functions that enable dynamic code generation or loading.
|
||||
- **Error Handling:** Providing informative error messages when a security violation occurs, including the specific function or variable that triggered the rejection and its location within the AST.
|
||||
- **Performance Consideration:** Optimizing the AST walking and whitelist lookup to minimize overhead on Elisp evaluation. Memoization of whitelist checks should be implemented to avoid redundant lookups.
|
||||
** Skill Definition
|
||||
#+begin_src lisp :tangle ../src/safety-harness.lisp
|
||||
(defskill :skill-safety-harness
|
||||
:priority 90
|
||||
:trigger (lambda (ctx) nil)
|
||||
:neuro nil
|
||||
:symbolic nil)
|
||||
#+end_src
|
||||
|
||||
** 2. Semantic Interfaces
|
||||
* Phase E: Chaos (Verification)
|
||||
#+begin_src lisp :tangle ../tests/safety-harness-tests.lisp
|
||||
(defpackage :org-agent-safety-tests
|
||||
(:use :cl :fiveam :org-agent)
|
||||
(:export #:safety-suite))
|
||||
(in-package :org-agent-safety-tests)
|
||||
|
||||
*** Function: +safety-harness-validate+
|
||||
(def-suite safety-suite :description "Tests for the Global Safety Harness.")
|
||||
(in-suite safety-suite)
|
||||
|
||||
#+BEGIN_SRC lisp
|
||||
(defun +safety-harness-validate+ (form whitelist)
|
||||
"Validates an Elisp form against a security whitelist.
|
||||
FORM: The Elisp form to validate (list or symbol).
|
||||
WHITELIST: An alist associating symbols (function/variable names) to metadata. Metadata includes :safe? boolean flag and :trust-level (integer).")
|
||||
#+END_SRC
|
||||
(test test-basic-math-safe
|
||||
(is (org-agent:safety-harness-validate "(+ 1 2)")))
|
||||
|
||||
*** Function: +safety-harness-ast-walk+
|
||||
(test test-blocked-eval
|
||||
(is (not (org-agent:safety-harness-validate "(eval '(+ 1 2))"))))
|
||||
|
||||
#+BEGIN_SRC lisp
|
||||
(defun +safety-harness-ast-walk+ (form whitelist)
|
||||
"Recursively walks the Abstract Syntax Tree (AST) of an Elisp form,
|
||||
validating each node against the whitelist.")
|
||||
#+END_SRC
|
||||
(test test-blocked-shell
|
||||
(is (not (org-agent:safety-harness-validate "(uiop:run-program \"ls\")"))))
|
||||
|
||||
*** Function: +safety-harness-whitelist-lookup+
|
||||
|
||||
#+BEGIN_SRC lisp
|
||||
(defun +safety-harness-whitelist-lookup+ (symbol whitelist)
|
||||
"Looks up a symbol in the security whitelist.
|
||||
Returns the whitelist entry if found, or nil if not found.")
|
||||
#+END_SRC
|
||||
|
||||
*** Function: +safety-harness-eval-blocked?+
|
||||
|
||||
#+BEGIN_SRC lisp
|
||||
(defun +safety-harness-eval-blocked?+ (form)
|
||||
"Checks if the Elisp form contains any prohibited eval-like constructs.
|
||||
Returns t if eval is blocked, nil otherwise.")
|
||||
#+END_SRC
|
||||
|
||||
*** Data Structure: +safety-harness-error+
|
||||
|
||||
A plist data structure representing a security violation:
|
||||
- `:type`: `'whitelist-violation` or `'eval-blocked`
|
||||
- `:symbol`: The offending symbol (function or variable name)
|
||||
- `:location`: A list representing the path within the AST where the violation occurred.
|
||||
(test test-nested-unsafe
|
||||
(is (not (org-agent:safety-harness-validate "(let ((x 1)) (delete-file \"test.txt\"))"))))
|
||||
|
||||
(test test-safe-kernel-api
|
||||
(is (org-agent:safety-harness-validate "(org-agent::lookup-object \"node-1\")")))
|
||||
#+end_src
|
||||
|
||||
Reference in New Issue
Block a user