Putting your rbenv-managed bundler-specified executables in your PATH (more) securely
There have been a smattering of solutions offered over the years for getting rid of bundle exec. To me they all have drawbacks -- they either solve the problem at the wrong layer, involve remembering an extra step, require a manually-managed whitelist, or are messy for some other reason.
- carsomyr/rbenv-bundler
- gma/bundler-exec
- mpapis/rubygems-bundler
- various flavors of
bundle exec bash: here's one, here's my own quick experiment that I never used - various flavors of adding ./bin to your path: David Chelimsky post and the comments on this blog post
The last one is my favorite -- it uses native shell and bundler features in a straightforward way. However, it's considered a security risk to have
./binin your path. Someone could trick you into downloading something that youcdinto which has a script in./bin/lsthat deletes your home directory or reads your personal information.
Here is my solution to that. If you are using zsh, you can execute arbitrary shell code whenever cd is invoked. So here, I add ./bin to PATH, but only when there is a Gemfile present. Put this somewhere in your zsh config:
function chpwd {
if [ -r $PWD/Gemfile ]; then
export PATH=./bin:${PATH//\.\/bin:}
else
regexp-replace PATH '\./bin:' ''
fi
}
Ta-da! Now you just have to remember to use the --binstubs flag whenever you install new gems. This part could be more smoothly handled by Bunder, I've opened a ticket to begin exploring this issue and might put together a solution sometime.
notes
- There is still a security risk when downloading projects with
Gemfilepresent, but now it's much smaller. An alternative would be to check for.my_special_fileinstead of Gemfile -- that file would have to have a non-standard name in order to be fully secure. Eventually I want to switch to this even more secure method, but I can't think of an elegant way to pick its name, so I'm sticking with Gemfile :-D. - if you have something already defined in
chpwd, you have to put this code inside the samechpwd-- consecutivechpwds will overwrite each other. This also stops me from making a flexible oh-my-zsh plugin. If anyone knows how to addchpwdbehavior without overwriting previouschpwdbehavior, let me know! - It works with foreman too --
foreman run foowill use the correct executable andforeman run which fooshows the correct path. However for some reasonforeman run type foodoes not -- I guesstypestarts a fresh environment for some reason? - Next I would like to automatically prepend everything with
foreman run:-D I imagine that will be hackier though. Any ideas?