CVE-2018-11756 (PHP, published 2018-07-23T17:29Z)
Description: value: In PHP Runtime for Apache OpenWhisk, a Docker action inheriting one of the Docker tags openwhisk/action-php-v7.2:1.0.0 or openwhisk/action-php-v7.1:1.0.1 (or earlier) may allow an attacker to replace the user function inside the container if the user code is vulnerable to code exploitation.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/apache/incubator-openwhisk-runtime-php
Files changed:
core/php7.1Action/CHANGELOG.md
core/php7.1Action/router.php
core/php7.2Action/CHANGELOG.md
core/php7.2Action/router.php
tests/src/test/scala/runtime/actionContainers/Php7ActionContainerTests.scala
Commit message: Update tests to pick up upstream changes.


Vulnerable code:
        throw new RuntimeException("No code to execute");
        throw new RuntimeException("No code to execute");
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
</pydev_project>
  // note: "out" will not be empty as the PHP web server outputs a message when
  // it starts up
  lazy val phpContainerImageName = "action-php-v7.x"
  testEcho(Seq {
    (
      "PHP",
          |<?php
          |function main(array $args) : array {
          |    echo 'hello stdout';
          |    error_log('hello stderr');
          |    return $args;
          |}
          """.stripMargin)
  })

  testNotReturningJson("""
        |function main(array $args) {
        |    return "not a json object";
        """.stripMargin)
  testUnicode(Seq {
    (
      "PHP",
  })
  testEnv(
    Seq {
      (
        "PHP",
        """
         |<?php
         |function main(array $args) : array {
         |    return [
         |       "env" => $_ENV,
         |       "api_host" => $_ENV['__OW_API_HOST'],
         |       "api_key" => $_ENV['__OW_API_KEY'],
         |       "namespace" => $_ENV['__OW_NAMESPACE'],
         |       "action_name" => $_ENV['__OW_ACTION_NAME'],
         |       "activation_id" => $_ENV['__OW_ACTIVATION_ID'],
         |       "deadline" => $_ENV['__OW_DEADLINE'],
         |    ];
         |}
         """.stripMargin.trim)
    },
    enforceEmptyOutputStream)

  testInitCannotBeCalledMoreThanOnce("""
          |<?php
          |function main(array $args) : array {
          |    echo 'hello stdout';
          |    error_log('hello stderr');
          |    return $args;
          |}
          """.stripMargin)
  it should "fail to initialize with no code" in {
    val (out, err) = withPhp7Container { c =>
      val code = ""

      val (initCode, error) = c.init(initPayload(code))

      initCode should not be (200)
      error shouldBe a[Some[_]]
      error.get shouldBe a[JsObject]
      error.get.fields("error").toString should include("No code to execute")
    }
  }

  it should "support actions using non-default entry point" in {
    val (out, err) = withPhp7Container { c =>
      val code = """
            | <?php
            | function niam(array $args) {
            |     return [result => "it works"];
            | }
            """.stripMargin

      c.init(initPayload(code, main = "niam"))._1 should be(200)
      val (runCode, runRes) = c.run(runPayload(JsObject()))
      runRes.get.fields.get("result") shouldBe Some(JsString("it works"))
    }
  }


Fixed code:
## 1.0.2
Changes:
  - Disallow re-initialization of function.

        throw new RuntimeException("Missing main/no code to execute.");
## 1.0.1
Changes:
  - Disallow re-initialization of function.

        throw new RuntimeException("Missing main/no code to execute.");
  // note: "out" will not be empty as the PHP web server outputs a message when it starts up
  lazy val phpContainerImageName: String = ???
  override val testNoSourceOrExec = TestConfig("")

  override val testNotReturningJson = {
    TestConfig(
      """
       |<?php
       |function main(array $args) {
       |    return "not a json object";
       |}
     """.stripMargin,
      enforceEmptyOutputStream = enforceEmptyOutputStream,
      enforceEmptyErrorStream = false)
  }

  override val testInitCannotBeCalledMoreThanOnce = {
    TestConfig(
        |function main(array $args) : array {
        |    return $args;
      """.stripMargin,
      enforceEmptyOutputStream = enforceEmptyOutputStream)
  }
  override val testEntryPointOtherThanMain = {
    TestConfig(
        | <?php
        | function niam(array $args) {
        |     return $args;
        | }
      """.stripMargin,
      main = "niam",
      enforceEmptyOutputStream = enforceEmptyOutputStream)
  }

  override val testEcho = {
    TestConfig("""
                 |<?php
                 |function main(array $args) : array {
                 |    echo 'hello stdout';
                 |    error_log('hello stderr');
                 |    return $args;
                 |}
               """.stripMargin)
  }

  override val testUnicode = {
    TestConfig("""
  }
  override val testEnv = {
    TestConfig(
      """
        |<?php
        |function main(array $args) : array {
        |    return [
        |       "env" => $_ENV,
        |       "api_host" => $_ENV['__OW_API_HOST'],
        |       "api_key" => $_ENV['__OW_API_KEY'],
        |       "namespace" => $_ENV['__OW_NAMESPACE'],
        |       "action_name" => $_ENV['__OW_ACTION_NAME'],
        |       "activation_id" => $_ENV['__OW_ACTIVATION_ID'],
        |       "deadline" => $_ENV['__OW_DEADLINE'],
        |    ];
        |}
      """.stripMargin.trim,
      enforceEmptyOutputStream = enforceEmptyOutputStream)
  }

  override val testLargeInput = {
    TestConfig("""
                 |<?php
                 |function main(array $args) : array {
                 |    echo 'hello stdout';
                 |    error_log('hello stderr');
                 |    return $args;
                 |}
               """.stripMargin)
  }