31 Oct, 2009, JohnnyStarr wrote in the 1st comment:
Votes: 0
Ok, I know I've started a lot of Ruby threads, but I'm on a kick so here comes another…

I was thinking about using Procs as a sort of script for resets. I dont necessarily mean sandboxing, but it would be an easy way to load game objects. When it comes time to repop,
you could just say "room.reset" which runs that rooms individual script.

I guess the smart thing to do is create a sandbox, but is that really needed when me and my
friends are the only builders?
31 Oct, 2009, David Haley wrote in the 2nd comment:
Votes: 0
Generally speaking, it's probably good to sandbox things even if "you" are the only user, because (a) it will make it far easier when you are no longer the only user, and (b) it will make it easier to protect yourself from accidental mistakes. Nick Gammon gave some examples of scripting resets into procedures in this thread from a couple of years ago; it's all in Lua but hopefully the general idea will be clear and easily adaptable for you. I don't believe he really covers sandboxing, though. Still, the system is quite flexible in general, and there is a little bit of discussion there about this approach in general.
31 Oct, 2009, Cratylus wrote in the 3rd comment:
Votes: 0
David Haley said:
it's all in Lua


Did anybody ask for Lua around here? I didn't. Anyone?
31 Oct, 2009, Runter wrote in the 4th comment:
Votes: 0
Cratylus said:
David Haley said:
it's all in Lua


Did anybody ask for Lua around here? I didn't. Anyone?


Oh, Crat.
31 Oct, 2009, Runter wrote in the 5th comment:
Votes: 0
staryavsky said:
Ok, I know I've started a lot of Ruby threads, but I'm on a kick so here comes another…

I was thinking about using Procs as a sort of script for resets. I dont necessarily mean sandboxing, but it would be an easy way to load game objects. When it comes time to repop,
you could just say "room.reset" which runs that rooms individual script.

I guess the smart thing to do is create a sandbox, but is that really needed when me and my
friends are the only builders?


Maybe you can give a quick example of what you mean exactly by using Procs as a script?

On a side note, you might look at how you can use #eval to execute code saved as a string. It's pretty interesting, really.
31 Oct, 2009, JohnnyStarr wrote in the 6th comment:
Votes: 0
You know, I guess #eval does exactly what I had in mind. Thanks for the tip.
So here's an example:
# in room object
@script << "@mobs << world.create_mob_index['shire.mob.bilbo']"

# so when the timer for the rooms repop goes off do
room.script.call # or something to that effect

# or using eval?
eval(room.script)

Ok, so maybe this is just pseudo code, but I think the point comes across.
So, the best choice would be a sandbox. I just don't know how to go about it.
31 Oct, 2009, Runter wrote in the 7th comment:
Votes: 0
Yeah, I'm not really sure what you want to sandbox. You want to make it so people who have access to writing the scripts should only be limited to certain facilities in the language?
31 Oct, 2009, Tyche wrote in the 8th comment:
Votes: 0
Yes, sandboxing code is pretty easy to do in Ruby.

Following links to embedding LUA in C is about as helpful and useful as posting pictures of turds.
31 Oct, 2009, David Haley wrote in the 9th comment:
Votes: 0
Tyche said:
Following links to embedding LUA in C is about as helpful and useful as posting pictures of turds.

Then it's a good thing nobody linked to a discussion of embedding Lua in C, although it would appear that some of us have reading deficiencies.
Seriously dude, this is getting old. Why are you turning this into some kind of personal war? Are you going to keep up this harassment in every thread from now on?

Runter said:
Yeah, I'm not really sure what you want to sandbox. You want to make it so people who have access to writing the scripts should only be limited to certain facilities in the language?

That's the idea, yes. The problem with a full eval is that people can stick whatever they want in there. If you have trusted authors, then you can be pretty sure (hopefully) that they won't be doing things maliciously. But it's still possible to accidentally make mistakes that might not call sys.exit() (or whatever the equivalent is) but might loop incorrectly, etc.
Of course, the real danger isn't code from trusted authors, if you generally assume that they know what they're doing. Having a nice sandboxed environment where certain functions are disabled (OS and process control, especially, in addition to MUD control) makes it much safer to let more people write code. Even if you trust them to not maliciously harm things, you might not trust them to always know what they're doing. And, you can lower the bar on trust slightly if you know they can't delete things randomly.
31 Oct, 2009, JohnnyStarr wrote in the 10th comment:
Votes: 0
Ok, well that's very helpful. I was google'ing ruby sandbox gems and there seems to be some out there.
Tyche said:
Yes, sandboxing code is pretty easy to do in Ruby.

Do you think you could show an example?
Is FARTs ruby through a sandbox, or did you just decide to create your own mini scripting language?
01 Nov, 2009, Runter wrote in the 11th comment:
Votes: 0
staryavsky said:
Ok, well that's very helpful. I was google'ing ruby sandbox gems and there seems to be some out there.
Tyche said:
Yes, sandboxing code is pretty easy to do in Ruby.

Do you think you could show an example?
Is FARTs ruby through a sandbox, or did you just decide to create your own mini scripting language?


It would actually be an example I would like to see as well. I'm coming up pretty empty on google search.
01 Nov, 2009, David Haley wrote in the 12th comment:
Votes: 0
Is it possible in Ruby to run a function in an environment where you specify the global table yourself? This is an easy way of creating a sandbox, because you just don't make available those functions you don't want (e.g., OS functions).

There are several examples using Ruby gems for making sandboxes; the first result of "ruby restricted sandbox" is this page. That said, it claims that several of the gems out there are hacky/dirty, or only available for certain Ruby implementations (e.g. JRuby).
01 Nov, 2009, JohnnyStarr wrote in the 13th comment:
Votes: 0
I know that you can adjust the $SAFE setting 0 - 4 I believe. $SAFE will dictate how expressions are evaluated with #eval.
You can set it higher so that it wont allow tainted objects and "this" and "that". But I don't know of anything else.
I like the look of this gem you brought up. I'll give it a look-see.

Also, I came up with a cool name for "my" scripting language, just in case.
LEGOS!
Logical Expressive Game Object Script
Well, I thought it was kinda cool :redface:
01 Nov, 2009, JohnnyStarr wrote in the 14th comment:
Votes: 0
I've been playing with the idea of (LEGOS) using Ruby. So far I've had tons of fun with it:
class Operator
attr_reader :glyph, :method, :priority
def initialize(g,m,p)
@glyph, @method, @priority = g,m,p
end

def plus(l,r)
e = l + r
e.to_s
end

def minus(l,r)
e = l - r
e.to_s
end

def times(l,r)
e = l * r
e.to_s
end

def divide(l,r)
e = l / r
e.to_s
end

def assign(l,r)
l = r
l.to_s
end
end



# Test


require 'operator'

operators = [
Operator.new("+", :plus, 1),
Operator.new('-', :minus, 1),
Operator.new('/', :divide, 1),
Operator.new('*', :times, 1),
Operator.new('=', :assign, 2)
]

l = 100
r = 200

operators.each {|e| p l.to_s << " " << e.glyph << " " << r.to_s << " = " << e.send(e.method, l, r)}


OUTPUT:

"100 + 200 = 300"
"100 - 200 = -100"
"100 / 200 = 0"
"100 * 200 = 20000"
"100 = 200 = 200"


Like I said, just playing around, but I think this might be a good learning experience.
01 Nov, 2009, Tyche wrote in the 15th comment:
Votes: 0
staryavsky said:
Tyche said:
Yes, sandboxing code is pretty easy to do in Ruby.

Do you think you could show an example?


require 'pp'

module Kernel
def sandbox
Thread.new {
$SAFE = 4
yield
}.join
end
end

class Monster
attr_accessor :state, :level
def initialize s, l
@state, @level = s, l
end
end

# The test script code
script = <<EOD
obj.state = :attack
obj.level = 20
EOD

obj = Monster.new :alert, 16
pp obj
pp obj.tainted?
# Allow object to be used
obj.taint
sandbox do
eval script
end

# Insert code to check object

pp obj
pp obj.tainted?
# Set object to untainted
obj.untaint

# Script should crash with security error here
sandbox do
eval script
end


Note this is very very restrictive in term of what you may do. And there is no guarantee that the object(s) exposed to the script are modified in unseemly ways. You can of course write code to examine the objects you've expose to make sure they are still okay. Also a script can be written to loop forever. This can be mitigated by writing a monitor thread that kills scripts that exceed some time threshold.

staryavsky said:
Is FARTs ruby through a sandbox, or did you just decide to create your own mini scripting language?


Yes it's the latter, which has the side effect of being "safe" because nothing "unsafe" was implemented.
It may be a better choice because you can implement a domain specific language that might make more sense to builders and players.
Perhaps one that is based on the familar command interface of the mud itself, like Mushcode is to Mushes or MobProgs is to MercMuds.
02 Nov, 2009, David Haley wrote in the 16th comment:
Votes: 0
Tyche said:
This can be mitigated by writing a monitor thread that kills scripts that exceed some time threshold.

Are there hooks into the number of instructions executed, or would that require writing C code to poke at the interpreter's internals? Instruction counts can sometimes be a better metric than time, at least if time is wall time and not CPU time.
02 Nov, 2009, Tyche wrote in the 17th comment:
Votes: 0
David Haley said:
Are there hooks into the number of instructions executed…


Not in any of the Ruby implementations I've used.
20 Dec, 2009, Runter wrote in the 18th comment:
Votes: 0
This is a bit late, so I apologize if it isn't fresh any more. :)

Are all objects that are tainted exposed to any script?

Also, I don't really understand the part about needing to write code to examine exposed objects to make sure they are still okay. Typically what could be wrong with the objects? Perhaps just invalid data?

Edit:

Also with the code you posted, Tyche, I'm getting the security error at the first eval that was expected at the second.

obj.taint
sandbox do
@@ eval script
end


"in `eval': Insecure: can't modify instance variable (SecurityError)"
20 Dec, 2009, Runter wrote in the 19th comment:
Votes: 0
After a little testing I'm having trouble doing a large number of things I would expect to be able to do from inside of the sandbox. Is the answer to this actually lowering the safe level?


Actually, it seems like it doesn't matter if it's tainted or not. I get the same security results. Hrm.

I'm using 1.9.1 if it matters.
20 Dec, 2009, Tyche wrote in the 20th comment:
Votes: 0
Runter said:
Are all objects that are tainted exposed to any script?


Any object in the current binding context when eval is invoked, which would be global and local variables. At safe level 4, you can't use untainted objects or globals.

Runter said:
Also, I don't really understand the part about needing to write code to examine exposed objects to make sure they are still okay. Typically what could be wrong with the objects? Perhaps just invalid data?


It's possible their properties could be set by a script to unexpected/invalid data. So yes, any sanity checks on the objects properties need to be done on those that would matter. For example, if you allowed an object that holds data fed into a SQL engine in a property to be seen by a script, you ought to make sure to check/escape that data before untainting.

Runter said:
I'm using 1.9.1 if it matters.


I'm using 1.8, so I'll bet it does matter. I'm not sure what changes they may have made to it.
0.0/24