CVE-2018-11757: Insufficient Information (NVD-CWE-noinfo)
value: In Docker Skeleton Runtime for Apache OpenWhisk, a Docker action inheriting the Docker tag openwhisk/dockerskeleton:1.3.0 (or earlier) may allow an attacker to replace the user function inside the container if the user code is vulnerable to code exploitation.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 9.8
Published: 2018-07-23T17:29Z
Repository: https://github.com/apache/incubator-openwhisk-runtime-docker
Language: Python
Files changed: core/actionProxy/actionproxy.py, tests/src/test/scala/runtime/actionContainers/ActionProxyContainerTests.scala
Commit date: 2018-07-05 16:31:10 -0400
Commit message: Do not allow re-init of the action exec.

Disables re-initialization of the executable unless explicitly permitted
via an environment variable PROXY_ALLOW_REINIT == "1", which is generally
useful for local testing and development.

Diff: diff --git a/core/actionProxy/actionproxy.py b/core/actionProxy/actionproxy.py
index bbe9902..0bca409 100644
--- a/core/actionProxy/actionproxy.py
+++ b/core/actionProxy/actionproxy.py
@@ -201,20 +201,30 @@ class ActionRunner:
             print('err', str(e))
             return False
 
 proxy = flask.Flask(__name__)
 proxy.debug = False
+# disable re-initialization of the executable unless explicitly allowed via an environment
+# variable PROXY_ALLOW_REINIT == "1" (this is generally useful for local testing and development)
+proxy.rejectReinit = 'PROXY_ALLOW_REINIT' not in os.environ or os.environ['PROXY_ALLOW_REINIT'] != "1"
+proxy.initialized = False
 runner = None
 
-
 def setRunner(r):
     global runner
     runner = r
 
 
 @proxy.route('/init', methods=['POST'])
 def init():
+    if proxy.rejectReinit is True and proxy.initialized is True:
+        msg = 'Cannot initialize the action more than once.'
+        sys.stderr.write(msg + '\n')
+        response = flask.jsonify({'error': msg})
+        response.status_code = 403
+        return complete(response)
+
     message = flask.request.get_json(force=True, silent=True)
     if message and not isinstance(message, dict):
         flask.abort(404)
     else:
         value = message.get('value', {}) if message else {}
@@ -226,10 +236,11 @@ def init():
         status = runner.init(value)
     except Exception as e:
         status = False
 
     if status is True:
+        proxy.initialized = True
         return ('OK', 200)
     else:
         response = flask.jsonify({'error': 'The action failed to generate or locate a binary. See logs for details.'})
         response.status_code = 502
         return complete(response)
diff --git a/tests/src/test/scala/runtime/actionContainers/ActionProxyContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/ActionProxyContainerTests.scala
index 20a9ee5..52022ee 100644
--- a/tests/src/test/scala/runtime/actionContainers/ActionProxyContainerTests.scala
+++ b/tests/src/test/scala/runtime/actionContainers/ActionProxyContainerTests.scala
@@ -243,6 +243,7 @@ class ActionProxyContainerTests extends BasicActionRunnerTests with WskActorSyst
   testNotReturningJson(codeNotReturningJson, checkResultInLogs = true)
   testEcho(stdCodeSamples)
   testUnicode(stdUnicodeSamples)
   testEnv(stdEnvSamples)
   testLargeInput(stdLargeInputSamples)
+  testInitCannotBeCalledMoreThanOnce(codeNotReturningJson) // any code sample will do
 }

Fixed code: # disable re-initialization of the executable unless explicitly allowed via an environment
# variable PROXY_ALLOW_REINIT == "1" (this is generally useful for local testing and development)
proxy.rejectReinit = 'PROXY_ALLOW_REINIT' not in os.environ or os.environ['PROXY_ALLOW_REINIT'] != "1"
proxy.initialized = False
    if proxy.rejectReinit is True and proxy.initialized is True:
        msg = 'Cannot initialize the action more than once.'
        sys.stderr.write(msg + '\n')
        response = flask.jsonify({'error': msg})
        response.status_code = 403
        return complete(response)

        proxy.initialized = True
  testInitCannotBeCalledMoreThanOnce(codeNotReturningJson) // any code sample will do