Commit 7cd8ffff by Arjun Singh

Cleans up node calls and (barely) improves security as subprocess.Popen will…

Cleans up node calls and (barely) improves security as subprocess.Popen will escape arguments properly. This means that instructors cannot set the grader/generator to ;/bin/rm -rf *; however, the python and node environments are not sandboxed at all and so instructors can still run arbitrarily malicious code.
parent fb6dbb12
...@@ -20,6 +20,7 @@ import traceback ...@@ -20,6 +20,7 @@ import traceback
import hashlib import hashlib
import abc import abc
import os import os
import subprocess
import xml.sax.saxutils as saxutils import xml.sax.saxutils as saxutils
# specific library imports # specific library imports
...@@ -297,7 +298,6 @@ class JavascriptResponse(LoncapaResponse): ...@@ -297,7 +298,6 @@ class JavascriptResponse(LoncapaResponse):
if self.generator: if self.generator:
self.problem_state = self.generate_problem_state() self.problem_state = self.generate_problem_state()
print self.problem_state
else: else:
self.problem_state = None self.problem_state = None
...@@ -370,17 +370,19 @@ class JavascriptResponse(LoncapaResponse): ...@@ -370,17 +370,19 @@ class JavascriptResponse(LoncapaResponse):
def generate_problem_state(self): def generate_problem_state(self):
js_dir = os.path.join(self.system.filestore.root_path, 'js') js_dir = os.path.join(self.system.filestore.root_path, 'js')
node_path = os.path.normpath(js_dir) tmp_env = os.environ.copy()
node_path = tmp_env["NODE_PATH"] + ":" + os.path.normpath(js_dir)
tmp_env["NODE_PATH"] = node_path
generator_file = os.path.dirname(os.path.normpath(__file__)) + '/javascript_problem_generator.js' generator_file = os.path.dirname(os.path.normpath(__file__)) + '/javascript_problem_generator.js'
command = "NODE_PATH=$NODE_PATH:%s node %s %s '%s' '%s' '%s'" % (node_path, output = subprocess.check_output(["node",
generator_file, generator_file,
self.generator, self.generator,
json.dumps(self.generator_dependencies), json.dumps(self.generator_dependencies),
json.dumps(self.system.seed), json.dumps(self.system.seed),
json.dumps(self.params)) json.dumps(self.params)
node_process = os.popen(command) ],
output = node_process.readline().strip() env=tmp_env).strip()
node_process.close()
return json.loads(output) return json.loads(output)
def extract_params(self): def extract_params(self):
...@@ -423,22 +425,25 @@ class JavascriptResponse(LoncapaResponse): ...@@ -423,22 +425,25 @@ class JavascriptResponse(LoncapaResponse):
def run_grader(self, submission): def run_grader(self, submission):
if submission is None or submission == '': if submission is None or submission == '':
submission = json.dumps(None) submission = json.dumps(None)
js_dir = os.path.join(self.system.filestore.root_path, 'js') js_dir = os.path.join(self.system.filestore.root_path, 'js')
node_path = os.path.normpath(js_dir) tmp_env = os.environ.copy()
node_path = tmp_env["NODE_PATH"] + ":" + os.path.normpath(js_dir)
tmp_env["NODE_PATH"] = node_path
grader_file = os.path.dirname(os.path.normpath(__file__)) + '/javascript_problem_grader.js' grader_file = os.path.dirname(os.path.normpath(__file__)) + '/javascript_problem_grader.js'
command = "NODE_PATH=$NODE_PATH:%s node %s '%s' '%s' '%s' '%s' '%s'" % (node_path, outputs = subprocess.check_output(["node",
grader_file, grader_file,
self.grader, self.grader,
json.dumps(self.grader_dependencies), json.dumps(self.grader_dependencies),
submission, submission,
json.dumps(self.problem_state), json.dumps(self.problem_state),
json.dumps(self.params)) json.dumps(self.params)
print command ],
node_process = os.popen(command) env=tmp_env).split('\n')
all_correct = json.loads(node_process.readline().strip())
evaluation = node_process.readline().strip() all_correct = json.loads(outputs[0].strip())
solution = node_process.readline().strip() evaluation = outputs[1].strip()
node_process.close() solution = outputs[2].strip()
return (all_correct, evaluation, solution) return (all_correct, evaluation, solution)
def get_answers(self): def get_answers(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment