- Block frame / traceback introspection that recovers a runtime guard's original callable: the
open()/os.* guard wrappers hold the unguarded callable as a free variable (real), so a snippet
that triggers a denied open() could read it back via a trace hook or the caught exception's
traceback (frame.f_locals['real'], tb.tb_frame.f_locals) and call it directly. __closure__ /
cell_contents were already blocked, so the frame path was the remaining channel; add the frame
acquisition + value-read attributes (f_locals, f_globals, f_back, f_builtins, tb_frame,
tb_next, gi_frame, cr_frame, ag_frame, settrace, setprofile, _getframe, _current_frames,
currentframe) to the introspection-gadget set, flagged for any receiver in both the attribute
and getattr-string forms.
- Treat an opaque compile() source as executable: compile() does not itself run, but its code
object can be executed WITHOUT exec / eval (fn.__code__ = compile(src, '<p>', 'exec'); fn()),
so a non-literal compile source is as unverifiable as an opaque exec / eval payload and is now
blocked too. A literal compile source is still analyzed recursively and stays allowed.
- Treat a leading shell ! as command-position syntax: in bash ! negates the pipeline exit status
but the following word is still the executed command, so ! touch /tmp/escape / ! python3 -c ...
slipped past the child-writer / interpreter blocklist. Skip a command-position ! in the
command scanner and the wrapper-aware command-word resolver so the real command is scanned; a !
in argument position ([ ! -f x ], find . ! -name ...) is unaffected.
Adds TestRound31Bypasses.