diff --git a/installation/forms/setup.xml b/installation/forms/setup.xml
index bf07d1ecc6e33..055829fb78eaf 100644
--- a/installation/forms/setup.xml
+++ b/installation/forms/setup.xml
@@ -28,11 +28,14 @@
/>
wiki for more information."
+INSTL_USERNAME_INVALID="Please enter a valid username. No space at beginning or end, at least 2 characters and must not have the following characters: < > \ " ' % ; ( ) &."
INSTL_INSTALL_JOOMLA="Install Joomla"
INSTL_CONNECT_DB="Setup Database Connection"
diff --git a/installation/language/en-US/en-US.ini b/installation/language/en-US/en-US.ini
index 913c2b4e38ac2..d7f67f83145e4 100644
--- a/installation/language/en-US/en-US.ini
+++ b/installation/language/en-US/en-US.ini
@@ -66,6 +66,8 @@ INSTL_DATABASE_PREFIX_DESC="Enter a table prefix or use the randomly generated o
INSTL_DATABASE_TYPE_DESC="Select the database type."
INSTL_DATABASE_USER_DESC="Either a username you created or a username provided by your host."
INSTL_DATABASE_VALIDATION_ERROR="Check your database credentials, database type, database name or hostname. If you have MySQL 8 installed then please read this wiki for more information."
+INSTL_USERNAME_INVALID="Please enter a valid username. No space at beginning or end, at least 2 characters and must not have the following characters: < > \ " ' % ; ( ) &."
+
INSTL_INSTALL_JOOMLA="Install Joomla"
INSTL_CONNECT_DB="Setup Database Connection"
diff --git a/installation/src/Form/Rule/UsernameRule.php b/installation/src/Form/Rule/UsernameRule.php
new file mode 100644
index 0000000000000..a2ff377685564
--- /dev/null
+++ b/installation/src/Form/Rule/UsernameRule.php
@@ -0,0 +1,51 @@
+ tag for the form field object.
+ * @param mixed $value The form field value to validate.
+ * @param string $group The field name group control value. This acts as an array container for the field.
+ * For example if the field has name="foo" and the group value is set to "bar" then the
+ * full field name would end up being "bar[foo]".
+ * @param Registry $input An optional Registry object with the entire data set to validate against the entire form.
+ * @param Form $form The form object for which the field is being tested.
+ *
+ * @return boolean True if the value is valid, false otherwise.
+ */
+ public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null)
+ {
+ $filterInput = InputFilter::getInstance();
+
+ if (preg_match('#[<>"\'%;()&\\\\]|\\.\\./#', $value) || strlen(utf8_decode($value)) < 2
+ || $filterInput->clean($value, 'TRIM') !== $value
+ || strlen(utf8_decode($value)) > $element['size'])
+ {
+ return false;
+ }
+
+ return true;
+ }
+}