mueval: Safely evaluate Haskell expressions

[ bsd3, development, language, library, program ] [ Propose Tags ]

Mueval is a Haskell interpreter. It uses the GHC API to evaluate arbitrary Haskell expressions. Importantly, mueval takes many precautions to defang and avoid "evil" code. It uses resource limits, whitelisted modules, special Show instances for IO, threads, changes of directory, and so on to sandbox the Haskell code.

It is, in short, intended to be a standalone version of Lambdabot's famous evaluation functionality. For examples and explanations, please see the README file.

Mueval is currently POSIX-only.


[Skip to Readme]

Downloads

Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.2, 0.2.1, 0.3, 0.3.1, 0.4, 0.4.5, 0.4.6, 0.5, 0.5.1, 0.6, 0.6.1, 0.6.2, 0.6.3, 0.6.4, 0.7.0, 0.7.1, 0.8, 0.8.1, 0.8.2, 0.9, 0.9.1, 0.9.1.1, 0.9.1.1.2, 0.9.3, 0.9.4
Dependencies base, directory, filepath, hint (>=0.2.4), mtl, show (>=0.3), unix, utf8-string (<1) [details]
License BSD-3-Clause
Author Gwern
Maintainer Gwern <gwern0@gmail.com>
Revised Revision 1 made by AdamBergmark at 2015-06-11T10:27:47Z
Category Development, Language
Home page http://code.haskell.org/mubot/
Uploaded by GwernBranwen at 2008-08-20T20:54:33Z
Distributions Arch:0.9.3, Debian:0.9.3, FreeBSD:0.9.1.1.2, NixOS:0.9.4
Reverse Dependencies 5 direct, 1 indirect [details]
Executables mueval
Downloads 26596 total (52 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for mueval-0.6.3

[back to package description]
WHAT:
Mueval grew out of my discontent with Lambdabot: it's really neat to be able to run expressions like this:

07:53 < ivanm> > filter (\ x -> isLetter x || x == '\t') "asdf$#$     dfs"
07:55 < lambdabot>  "asdfdfs"

But Lambdabot is crufty and very difficult to install or run. IMO, we need a replacement or rewrite, but one of the things that make this difficult is that Lambdabot uses hs-plugins to get that sort of evaluation functionality, and hs-plugins is half the problem. We want some sort of standalone executable which provides that functionality. Now, 'ghc -e' is obviously unsuited because there is no sandboxing, so what I've done is basically marry the GHC API (as rendered less sharp-edged by Hint) with a bunch of resource limits and sandboxing (as largely stolen from Lambdabot).

EXAMPLES:
The end result is an adorable little program, which you can use like this:

 bash-3.2$ mueval --expression '1*100+1'
 Expression type: (Num t) => t
 result: "101"

 bash-3.2$ mueval --expression "filter (\`notElem\` ['A'..'Z']) \"abcXsdzWEE\""
 Expression type: [Char]
 result: "\"abcsdz\""

Note that mueval will avoid all the attacks I've been able to test on it:

 bash-3.2$ mueval --expression 'let x = x in x'
 Expression type: t
 result: "mueval: Time limit exceeded

 bash-3.2$ mueval --expression "let foo = readFile \"/etc/passwd\" >>= print in foo"
 Expression type: IO ()
 result: "<IO ()>"

 bash-3.2$ mueval --module System.IO.Unsafe --expression "let foo = unsafePerformIO readFile \"/etc/passwd\" in foo"
 mueval: Unknown or untrusted module supplied! Aborting.

LOADING FROM FILE:
Like Lambdabot, Mueval is capable of loading a file and its definitions. This is useful to get a kind of persistence. Suppose you have a file "L.hs", with a function 'bar = (+1)' in it; then 'mueval --loadfile=L.hs --expression="bar 1"' will evaluate to, as one would expect, '2'.

It's worth noting that definitions and module imports in the loaded *ARE NOT* fully checked like the expression is. The resource limits and timeouts still apply, but little else. So if you are dynamically adding functions and module imports, you *MUST* secure them yourself or accept the loss of security. Currently, all known 'evil' expressions cause Mueval to exit with an error (a non-zero exit code), so my advice is to do something like 'mueval --expression foo && echo "\n" >> L.hs && echo foo >> L.hs'.

SUMMARY:
Anyway, it's my hope that this will be useful as an example or useful in itself for people endeavouring to fix the Lambdabot situation or just in safely running code period.

GETTING:
You can download Mueval at the usual place: <http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mueval>. Mueval has a public darcs repository, at <http://code.haskell.org/mubot/> (in the mueval/ subdirectory). Contributions are of course welcomed.

INSTALLING:
Mueval depends on a few of the standard libraries, which you should have installed already, and also on the 'Hint' library <http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hint>; Hint is particularly essential as it is the very capable wrapper around the GHC API which Mueval uses. (Without Hint, this would've been even more painful to write). All of this is cabalized, so ideally installation will be as simple as:

 sh$ cabal install mueval

However, you can still manually download and unpack the Mueval tarball, and do the usual Cabal dance:

 sh$ runhaskell Setup configure
 sh$ runhaskell Setup build
 sh$ runhaskell Setup install

BUGS:
Mueval uses a number of techniques for security; particularly problematic seem to be the resource limits, as they have to be specified manually & statically in the source code and so will probably be broken somewhere somewhen. If you can successfully build &install Mueval, but running it on expressions leads to errors, please send me an email at <gwern0@gmail.com>. Include in the email all the output you see if you run the informal test suite:

 sh$ sh tests.sh