# Bug in ERb when using $SAFE\>=4

**URL:** <https://www.ruby-forum.com/t/bug-in-erb-when-using-safe-4/91007>\
**Category:** Ruby\
**Created:** [April 3, 2007, 7:51pm UTC](https://www.ruby-forum.com/t/bug-in-erb-when-using-safe-4/91007 "2007-04-03T19:51:48Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andy\_Morrow](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/df705f/32.png) [@Andy\_Morrow](https://www.ruby-forum.com/u/Andy_Morrow)\
**Post date:** [April 3, 2007, 7:51pm UTC](https://www.ruby-forum.com/t/bug-in-erb-when-using-safe-4/91007/1 "2007-04-03T19:51:48Z")

</div>

I’ve been working with ERB and trying to run it in a secure  
environment. (My goal is to allow end users to render templates in my  
Rails app.) There is what appears to me to be a bug in ERB when you  
try to run an object that was created with $SAFE \>= 4. Here’s the  
relevant code:  
(from erb.rb in class ERB starting on line #735)  
def result(b=TOPLEVEL\_BINDING)  
if @safe\_level  
th = Thread.start {  
$SAFE = @safe\_level  
eval(@src, b, (@filename || ‘(erb)’), 1) #problem  
}  
return th.value  
else  
return eval(@src, b, (@filename || ‘(erb)’), 1)  
end  
end  
The problem lies in passing TOPLEVEL\_BINDING to eval. Once $SAFE\>=4  
is set, a new binding is created and you’re no longer allowed to  
modify the original binding. There’s no option to pass eval the  
binding created after $SAFE is set inside the new thread. My modified  
version of the code reads like this:  
(from erb.rb in class ERB, line # 739)  
eval(@src, (@safe\_level==4? binding : b), (@filename || ‘(erb)’), 1)  
#no problem any more  
I’ve tested this a million times, and you can’t pass ERB a valid  
binding unless you set $SAFE\>=4 in your main app (and I can’t do  
that.) Am I just crazy? Did I miss something?  
Thanks,  
Andy Morrow
