Reputation: 650
I have created simple REPL
bot for scala
.
It runs in linux environment and processes written scala
code in dialogs and gives the result:
For example
user| 1+1
bot | res0: Int = 2
user| res0 + 3
bot | res1: Int = 5
...
I used scala interpreter API for this purpose.
Code which processes given string
as scala code:
private val settings = new Settings
settings.processArgumentString(
"""
|-deprecation
|-feature
|-Xfatal-warnings
|-Xlint
|-usejavacp
|""".stripMargin)
def run(code: String, id: Long): (Result, String) = {
stream.reset()
try {
val intp = intpMap.getOrElseUpdate(id, new IMain(settings, new PrintWriter(stream, true)))
timedRun(maxWorkTime)(intp.interpret(code)) -> stream.toString
} catch {
case e: TimeoutException => (Error, s"Долго считать - иди в пень")
}
}
But here is a problem in the following case: What if the user will try to access system files? For example will write string:
scala.sys.process.stringToProcess("ls /").!!
bot will give access to system files. I also tried this code snippet in https://scastie.scala-lang.org/ and got access to system files. But I think they run REPL in docker container and there is no problems with it.
Is there any ways to restrict a jvm instance running my bot from accessing system files, or may be I can restrict file access in REPL API configs?
At this time I'm doing analysis given string for 'scala.sys' or 'java.io' substrings, but I think it is not reliable.
And is there any other vulnerabilities in security?
Upvotes: 3
Views: 294
Reputation: 27535
As far as I can tell, the solution build into JVM is SecurityManager
.
You can use it to restrict access to various functionalities of JVM, like restricting access to files, requests, reflection, etc. I haven't tested it though (especially in the context of REPL) and it might happen that you will have issues restricting things in a way that won't prevent REPL from working at all.
Alternative, which I think would be more secure, would be running your REPL as a separate process with no access on system level - basically create a very restricted user, run second JVM in that process and communicate through some RPC - this way the operating system itself will take care of stopping all wicked users' attempts.
Though to be even safer I would combine both: running REPL in separate process with limited access on system level as well as SecurityManager
.
As you noticed Scastie solves this simply using Docker - if you configure Docker to limit the amount of CPU, memory and disk space per image, and don't expose anything from host to the image.
Then your "only" troubles are exploits like meltdown/spectre. But at this point, you should consult some security expert because SO might be too general for this.
Upvotes: 1