TL;DR: Ruby-only solutions can only use source_location
, so just redefine this to return something like ['/some/empty/file', 1]
. C hacks to the interpreter don't use source_location
, but you can prevent any use of C extensions by blocking/white-listing require
and friends.
For one, to be able to execute a Ruby script, you have to be able to read it...
But back to the question. I know Sourcify doesn't use any mystical method besides a little method on Proc and Method called source_location
, which gives the filename and line number were a method/proc is defined. I know from experience that this approach is very fragile, requires writing some sort of parser, and only sometimes works in legitimate situations. So, Sourcify is already out if you redefine source_location
in B to return something like /dev/null, line 0
and let Sourcify throw a not-Ruby-source exception.
From Pry's source, it seems that Pry uses the same source_location
approach, so two birds with one stone.
Now, there is another option for all of these libraries, which is to drop down to C and hack the interpreter to record source code. This is almost flawless. But we can still avoid the danger in one very simple way. Someone could include all of the code for Pry's method source in A. But you can't include inline C/C extensions without requiring a C library. So, the solution is obvious: Redefine require
and require_relative
and load
to either not work, or to only allow certain libraries. This way, you can keep out the C hacks.
On MRI, there is no way (from Ruby code) besides source_location
to do this. So there you go!
Edit: According to @banister, from MRI 2.0+ there is a binding_of_caller
method builtin that could replace source location. Nuke this too. ;)
Warning: Ruby is not a good language for this. If you can metaprogram them, they can probably metaprogram you unless you're in a different process.