CVE-2020-15263: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: In platform before version 9.4.4, inline attributes are not properly escaped. If the data that came from users was not escaped, then an XSS vulnerability is possible. The issue was introduced in 9.0.0 and fixed in 9.4.4.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2020-10-19T21:15Z
Repository: https://github.com/orchidsoftware/platform
Language: PHP
Files changed: CHANGELOG.md, src/Platform/Dashboard.php, src/Screen/Field.php, src/Screen/Fields/Upload.php, tests/Unit/Screen/Fields/InputTest.php
Commit date: 2020-10-19 16:23:38 +0300
Commit message: refs #1313 Escape inline attributes (#1314)


Diff: diff --git a/CHANGELOG.md b/CHANGELOG.md
index 62ea2c52..4d9f4177 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,10 +2,15 @@
 All notable changes to this project will be documented in this file.
 
 The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
 and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
 
+## 9.4.4 - 2020-10-19
+
+### Fixed
+- Escape inline attributes [#1313](https://github.com/orchidsoftware/platform/pull/1313)
+
 ## 9.4.3 - 2020-10-17
 
 ### Changed
 - Updated dependencies
 
diff --git a/src/Platform/Dashboard.php b/src/Platform/Dashboard.php
index 9f8c926a..d81d6c61 100644
--- a/src/Platform/Dashboard.php
+++ b/src/Platform/Dashboard.php
@@ -15,11 +15,11 @@ class Dashboard
     use Macroable;
 
     /**
      * ORCHID Version.
      */
-    public const VERSION = '9.4.3';
+    public const VERSION = '9.4.4';
 
     /**
      * The Dashboard configuration options.
      *
      * @var array
diff --git a/src/Screen/Field.php b/src/Screen/Field.php
index 4d74e860..e705ce4d 100644
--- a/src/Screen/Field.php
+++ b/src/Screen/Field.php
@@ -243,15 +243,17 @@ class Field implements Fieldable
      */
     protected function getAllowAttributes(): ComponentAttributeBag
     {
         $allow = array_merge($this->universalAttributes, $this->inlineAttributes);
 
-        $attribute = new ComponentAttributeBag($this->getAttributes());
+        $attributes = collect($this->getAttributes())
+            ->filter(function ($value, $attribute) use ($allow) {
+                return Str::is($allow, $attribute);
+            })->toArray();
 
-        return $attribute->filter(function ($value, $attribute) use ($allow) {
-            return Str::is($allow, $attribute);
-        });
+        return (new ComponentAttributeBag())
+            ->merge($attributes);
     }
 
     /**
      * @return ComponentAttributeBag
      */
diff --git a/src/Screen/Fields/Upload.php b/src/Screen/Fields/Upload.php
index 33389b34..4e09b0fb 100644
--- a/src/Screen/Fields/Upload.php
+++ b/src/Screen/Fields/Upload.php
@@ -79,11 +79,10 @@ class Upload extends Field
         'formtarget',
         'name',
         'multiple',
         'placeholder',
         'required',
-        'value',
         'groups',
         'storage',
         'media',
         'closeOnAdd',
     ];
diff --git a/tests/Unit/Screen/Fields/InputTest.php b/tests/Unit/Screen/Fields/InputTest.php
index 32f55201..91571ad1 100644
--- a/tests/Unit/Screen/Fields/InputTest.php
+++ b/tests/Unit/Screen/Fields/InputTest.php
@@ -66,6 +66,20 @@ class InputTest extends TestFieldsUnitCase
 
         $this->assertStringContainsString('data-name="Alexandr Chernyaev"', $input);
         $this->assertStringContainsString('data-location="Russia"', $input);
         $this->assertStringContainsString('data-hello="world!"', $input);
     }
+
+    public function testEscapeAttributes(): void
+    {
+        $input = (string) Input::make('name')->value('valueQuote"');
+
+        $this->assertStringContainsString('value="valueQuote&quot;"', $input);
+    }
+
+    public function testRemoveBooleanAttributes(): void
+    {
+        $input = (string) Input::make('name')->required(false);
+
+        $this->assertStringNotContainsString('required', $input);
+    }
 }

Vulnerable code:     public const VERSION = '9.4.3';
        $attribute = new ComponentAttributeBag($this->getAttributes());
        return $attribute->filter(function ($value, $attribute) use ($allow) {
            return Str::is($allow, $attribute);
        });
        'value',
Fixed code: ## 9.4.4 - 2020-10-19

### Fixed
- Escape inline attributes [#1313](https://github.com/orchidsoftware/platform/pull/1313)

    public const VERSION = '9.4.4';
        $attributes = collect($this->getAttributes())
            ->filter(function ($value, $attribute) use ($allow) {
                return Str::is($allow, $attribute);
            })->toArray();
        return (new ComponentAttributeBag())
            ->merge($attributes);

    public function testEscapeAttributes(): void
    {
        $input = (string) Input::make('name')->value('valueQuote"');

        $this->assertStringContainsString('value="valueQuote&quot;"', $input);
    }

    public function testRemoveBooleanAttributes(): void
    {
        $input = (string) Input::make('name')->required(false);

        $this->assertStringNotContainsString('required', $input);
    }