I am building a Node.JS application that involves redirecting user input into a server-side command. Of course, that could be catastrophic to security, so I desire to run the child command inside an SELinux sandbox
. (I do not want to run the entire application inside of a sandbox because I want the end users to each have their own workspace on the server.)
For example, for the purpose of demonstration, consider the command `cowsay`. In order to run a sandboxed cowsay, you need simply `sandbox cowsay`. Other than the behind-the-scenes security differences, the interface of `sandbox cowsay` should be the same as that of plain `cowsay`.
However, Node.JS responds differently to these two approaches. Consider the code:
var spawn = require('child_process').spawn;
var cmd = spawn("cowsay", ["hello"]); // line A (no sandbox)
var cmd = spawn("sandbox", ["cowsay", "hello"]); // line B (with sandbox)
Here is the output of the version with line A:
$ node run.js
< hello >
but here is the output of the version with line B instead:
$ node run.js
In other words, Node.JS does not seem to read the streams from sandbox's child process.
This behavior is exhibited only when SELinux is in "enforcing" mode. The sandbox version works fine when SELinux is in "permissive" (non-enforcing) mode.
This test can be performed using any command. For example, suppose we used the python command interpreter. What happens here is that the non-sandboxed `python` waits for something to be fed into its stdin from Node.JS, but the sandboxed `python` simply exists with code 0, without waiting.
What needs to happen in order for Node.JS to treat a sandboxed command the same as a non-sandboxed command?