Commit 252f7ffc authored by catch's avatar catch

Issue #2652850 by tstoeckler, mohit_aghera, idebr, hchonov, mbovan,...

Issue #2652850 by tstoeckler, mohit_aghera, idebr, hchonov, mbovan, rodrigoaguilera, jwilson3, pguillard, espurnes, dravenk, ainarend, handkerchief, alexpott: Title for details form elements is not set as '#markup' and it will be escaped, but all other form elements use '#markup' and are not escaped
parent 716f73dd
......@@ -251,6 +251,11 @@ function template_preprocess_details(&$variables) {
$variables['summary_attributes']['aria-pressed'] = $variables['summary_attributes']['aria-expanded'];
}
$variables['title'] = (!empty($element['#title'])) ? $element['#title'] : '';
// If the element title is a string, wrap it a render array so that markup
// will not be escaped (but XSS-filtered).
if (is_string($variables['title']) && $variables['title'] !== '') {
$variables['title'] = ['#markup' => $variables['title']];
}
$variables['description'] = (!empty($element['#description'])) ? $element['#description'] : '';
$variables['children'] = (isset($element['#children'])) ? $element['#children'] : '';
$variables['value'] = (isset($element['#value'])) ? $element['#value'] : '';
......
......@@ -570,6 +570,11 @@ function template_preprocess_datetime_wrapper(&$variables) {
if (!empty($element['#title'])) {
$variables['title'] = $element['#title'];
// If the element title is a string, wrap it a render array so that markup
// will not be escaped (but XSS-filtered).
if (is_string($variables['title']) && $variables['title'] !== '') {
$variables['title'] = ['#markup' => $variables['title']];
}
}
// Suppress error messages.
......
......@@ -501,4 +501,28 @@ public function testRevisionTranslationRendering() {
$this->assertNoText('First rev en title');
}
/**
* Test that title is not escaped (but XSS-filtered) for details form element.
*/
public function testDetailsTitleIsNotEscaped() {
$this->drupalLogin($this->administrator);
// Make the image field a multi-value field in order to display a
// details form element.
$edit = ['cardinality_number' => 2];
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_image/storage', $edit, t('Save field settings'));
// Make the image field non-translatable.
$edit = ['settings[node][article][fields][field_image]' => FALSE];
$this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
// Create a node.
$nid = $this->createEntity(['title' => 'Node with multi-value image field en title'], 'en');
// Add a French translation and assert the title markup is not escaped.
$this->drupalGet("node/$nid/translations/add/en/fr");
$markup = 'Image <span class="translation-entity-all-languages">(all languages)</span>';
$this->assertSession()->assertNoEscaped($markup);
$this->assertSession()->responseContains($markup);
}
}
......@@ -4,3 +4,6 @@ description: 'Support module for Form API tests.'
package: Testing
version: VERSION
core: 8.x
dependencies:
- file
- filter
......@@ -12,6 +12,40 @@
*/
class FormTestLabelForm extends FormBase {
/**
* An array of elements that render a title.
*
* @var array
*/
public static $typesWithTitle = [
'checkbox',
'checkboxes',
'color',
'date',
'datelist',
'datetime',
'details',
'email',
'fieldset',
'file',
'item',
'managed_file',
'number',
'password',
'password_confirm',
'radio',
'radios',
'range',
'search',
'select',
'tel',
'textarea',
'textfield',
'text_format',
'url',
'weight',
];
/**
* {@inheritdoc}
*/
......@@ -125,6 +159,21 @@ public function buildForm(array $form, FormStateInterface $form_state) {
],
'#required' => TRUE,
];
foreach (static::$typesWithTitle as $type) {
$form['form_' . $type . '_title_no_xss'] = [
'#type' => $type,
'#title' => "$type <script>alert('XSS')</script> is XSS filtered!",
];
// Add keys that are required for some elements to be processed correctly.
if (in_array($type, ['checkboxes', 'radios'], TRUE)) {
$form['form_' . $type . '_title_no_xss']['#options'] = [];
}
if ($type === 'datetime') {
$form['form_' . $type . '_title_no_xss']['#default_value'] = NULL;
}
}
return $form;
}
......
......@@ -2,6 +2,7 @@
namespace Drupal\Tests\system\Functional\Form;
use Drupal\form_test\Form\FormTestLabelForm;
use Drupal\Tests\BrowserTestBase;
/**
......@@ -96,6 +97,17 @@ public function testFormLabels() {
$this->assertTrue(!empty($elements), "Title/Label not displayed when 'visually-hidden' attribute is set in radios.");
}
/**
* Tests XSS-protection of element labels.
*/
public function testTitleEscaping() {
$this->drupalGet('form_test/form-labels');
foreach (FormTestLabelForm::$typesWithTitle as $type) {
$this->assertSession()->responseContains("$type alert('XSS') is XSS filtered!");
$this->assertSession()->responseNotContains("$type <script>alert('XSS')</script> is XSS filtered!");
}
}
/**
* Tests different display options for form element descriptions.
*/
......
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