I’m experimenting with ways to allow backend scripting for a web app. Lua seemed like an obvious choice and I found Lua (an Elixir package with a semi-confusing name) which is built off of Robert Virding’s luerl. Lua (the package) is quite nice in that it’s not just a wrapper. It has a nice API for exposing Elixir data to Lua scripts and importantly handles sandboxing.
I admittedly don’t have a clear question here, I’m mostly just wondering if anyone has any experience doing this and if it’s a terrible idea or not. I’m thinking of a usercase like Shopify’s legacy scripts where they let you just write plain Ruby, giving you limited access to objects for accomplishing things like creating more complex discounts than its UI can provide. I’m just experimenting to learn here and (probably) not trying to build my own Shopify
I think that you should consider using Dune with a separate node setup. For example, you can start a separate node where the user scripts are running and these scripts will communicate with main node through some API (REST or maybe just some erlang terms over TCP/socket)
Thanks for the reply! I’m aware of Dune but the idea is to have a more general scripting language for use in a hypothetical product used by mere mortals who would be offended by having to learn a valuable skill like Elixir or FP
Dave Lucia has talked about extensively using luerl for his product at tvlabs.ai to enable customer scripting. I was present for the codeBEAM talk given by Dave and Robert and the approach is compelling. My takeaway is that it is a good solution.
That makes sense since Dave Lucia is the author of Lua (the package). Thanks! Unfortunately the talk doesn’t seem to be on YouTube, but I’m still looking there. There is one by Robert about luerl which I’m about to watch. Thanks!
Latest elixirpodcast talked about a company making a safe ast thing that let them let people write elixir without fear of getting pwned.
I am not sure I would trust that myself tbf, but I think they have published some of that as open source.
However a key takeaway they mentioned in the podcast was that in their benchmarking of homegrown vs luerl vs deno etc lurerl was really fast, just a little behind homegrown thing.
We are talking microseconds here. That means that luerl will often be done executing before you have even transmitted the payload to the executor over tcp when using something like Dune or Deno.
Its also extremely simple to expose functions from your codebase to luerl.
And as Dave has said at a few conferences now, lua is a very good LLM target because its so simple grammar and logic. Meaning you can probably make great helpers if you have users who are only partial programmers.
And thanks, that’s all good info! I should have mentioned that I played with Lua (the package) a bunch before posting and yes, it’s reallllllly easy to pass variables and functions to scripts, sandbox, and call Lua in Elixir—it’s great!
I guess another thing I’m curious about is sandboxing in general. I’ve read how to do it (and Lua.ex does it out of the box) but have read several murmurings that it’s not perfect, or at least hard to get totally right. Of course none of these posts expand on that, so I’m trying to discover those kinds of pitfalls.
One thing to be on the lookout for luerl’s max_reductions and max_time options. Not only do you want to sandbox certain capabilities, but you likely want to protect against infinite loops and unbounded memory growth, or any other resources that could be exploited.
Ah yes, I read about this in a post about Lua sandboxing but have not yet looked into if Elixir Lua has it out of the box or not. Thanks for pointing me to right place in the luerl docs!
Its also worth noting that sandboxing io out of luerl (as it can potentially read disk) is trivial with overwriting one single table that holds the io module.
It is a bit weird how Sequin handwaves over this. It is literally a few lines of code vs something they must have sunk hundreds of engineering hours into (and frankly after reading their summary I would still go with luerl I think ).
At 100microsecs per invocation they would support everything trivially but not have to own the security posture of whitelisted AST. The sandboxing guarantees of luerl seems MUCH stronger than what they write out of their own lib in the article imo.
That said I am not a low level hacker or security expert, so I might also be wrong.
Ugh, you made me realize I’m That Guy who doesn’t post stuff they claimed to have found. On top of it, I’m Extra That Guy because it turns out I only thought I found it. I was watching Robert’s talk while searching and found and interview with Dave L about TV Labs and there was a result for a CodeBEAM duo talk with Robert and not-Dave. So sorry about that. I was just trying to find to actually find it with no luck. If anyone knows how to find it please let us know!
Lua er, I’m just going to call it Lua.ex because luex is actually a thing as well has a quite well-covered module blocklist for its sandbox. I would think you’d probably want to block the os module altogether for a web app as well as coroutine, though I’m not totally sure. I actually don’t know Lua very well. I read the entire book a couple of years ago without doing any of the exercises
Thanks for the interest in Lua! Apologies for the confusing name, I wanted it to be easy to write, and it kind of stuck.
I’m happy to answer any questions you may have. I note this in my blog post from yesterday, but Luerl is certainly lacking in the error message and stacktrace department. That is certainly something I hope to improve in the coming months with the help of Robert.
As for sandboxing goes, the underlying implementation of Luerl is still Erlang, so even doing string concatenation via "hello" .. "world" may cause a binary to be allocated. As far as I’m aware, this happens on the heap and is not local to the process, so sandboxing this particular behavior is difficult. One idea I’ve had here is for Luerl to inject tracing instructions into its own VM for measuring these allocations and tracking them in the runtime. There are currently no plans to do this, but I think it would be an interesting path to explore.
As for my conference talk from Code BEAM EU 2024 with Robert, that has not been posted yet.
One other thing worth mentioning, is that Robert has expressed interest in merging my library into Luerl. I have a few things that I want to agree on with him before this happens, but I am certainly interested in doing so.
As for Dune and Mini-Elixir, I think these are really interesting projects! I’ve chatted with Anthony at Sequin at length about Mini-Elixir, and I am quite interested in experimenting with them.
However, for my use case of using Lua as a compilation target, there are a lot of shortcuts I can take with outputting a object-oriented, mutable language. My hunch is that outputting Elixir would be a much more challenging task due to needing to track variables and propagating state, where with Lua, this can be hidden with method calls, etc.
To that end, I would love to have a different sandboxed language that was readable, an easy compilation target, and had great error messages. I’m not married to Lua, so I’m open to the possibility of switching.
With that being said, I get personal joy out of working on both Lua and Luerl, and I hope to see those libraries improve and grow!