You are here

function EditorSecurityTest::testSwitchingSecurity in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 core/modules/editor/src/Tests/EditorSecurityTest.php \Drupal\editor\Tests\EditorSecurityTest::testSwitchingSecurity()

Tests administrator security: is the user safe when switching text formats?

Tests 24 scenarios. Tests only with a text editor that is not XSS-safe.

When changing from a more restrictive text format with a text editor (or a text format without a text editor) to a less restrictive text format, it is possible that a malicious user could trigger an XSS.

E.g. when switching a piece of text that uses the Restricted HTML text format and contains a <script> tag to the Full HTML text format, the <script> tag would be executed. Unless we apply appropriate filtering.

File

core/modules/editor/src/Tests/EditorSecurityTest.php, line 308
Contains \Drupal\editor\Tests\EditorSecurityTest.

Class

EditorSecurityTest
Tests XSS protection for content creators when using text editors.

Namespace

Drupal\editor\Tests

Code

function testSwitchingSecurity() {
  $expected = array(
    array(
      'node_id' => 1,
      'value' => self::$sampleContent,
      // No text editor => no XSS filtering.
      'format' => 'restricted_without_editor',
      'switch_to' => array(
        'restricted_with_editor' => self::$sampleContentSecured,
        // Intersection of restrictions => most strict XSS filtering.
        'restricted_plus_dangerous_tag_with_editor' => self::$sampleContentSecured,
        // No text editor => no XSS filtering.
        'unrestricted_without_editor' => FALSE,
        'unrestricted_with_editor' => self::$sampleContentSecured,
      ),
    ),
    array(
      'node_id' => 2,
      'value' => self::$sampleContentSecured,
      // Text editor => XSS filtering.
      'format' => 'restricted_with_editor',
      'switch_to' => array(
        // No text editor => no XSS filtering.
        'restricted_without_editor' => FALSE,
        // Intersection of restrictions => most strict XSS filtering.
        'restricted_plus_dangerous_tag_with_editor' => self::$sampleContentSecured,
        // No text editor => no XSS filtering.
        'unrestricted_without_editor' => FALSE,
        'unrestricted_with_editor' => self::$sampleContentSecured,
      ),
    ),
    array(
      'node_id' => 3,
      'value' => self::$sampleContentSecuredEmbedAllowed,
      // Text editor => XSS filtering.
      'format' => 'restricted_plus_dangerous_tag_with_editor',
      'switch_to' => array(
        // No text editor => no XSS filtering.
        'restricted_without_editor' => FALSE,
        // Intersection of restrictions => most strict XSS filtering.
        'restricted_with_editor' => self::$sampleContentSecured,
        // No text editor => no XSS filtering.
        'unrestricted_without_editor' => FALSE,
        // Intersection of restrictions => most strict XSS filtering.
        'unrestricted_with_editor' => self::$sampleContentSecured,
      ),
    ),
    array(
      'node_id' => 4,
      'value' => self::$sampleContent,
      // No text editor => no XSS filtering.
      'format' => 'unrestricted_without_editor',
      'switch_to' => array(
        // No text editor => no XSS filtering.
        'restricted_without_editor' => FALSE,
        'restricted_with_editor' => self::$sampleContentSecured,
        // Intersection of restrictions => most strict XSS filtering.
        'restricted_plus_dangerous_tag_with_editor' => self::$sampleContentSecured,
        // From no editor, no security filters, to editor, still no security
        // filters: resulting content when viewed was already vulnerable, so
        // it must be intentional.
        'unrestricted_with_editor' => FALSE,
      ),
    ),
    array(
      'node_id' => 5,
      'value' => self::$sampleContentSecured,
      // Text editor => XSS filtering.
      'format' => 'unrestricted_with_editor',
      'switch_to' => array(
        // From editor, no security filters to security filters, no editor: no
        // risk.
        'restricted_without_editor' => FALSE,
        'restricted_with_editor' => self::$sampleContentSecured,
        // Intersection of restrictions => most strict XSS filtering.
        'restricted_plus_dangerous_tag_with_editor' => self::$sampleContentSecured,
        // From no editor, no security filters, to editor, still no security
        // filters: resulting content when viewed was already vulnerable, so
        // it must be intentional.
        'unrestricted_without_editor' => FALSE,
      ),
    ),
  );

  // Log in as the privileged user, and for every sample, do the following:
  //  - switch to every other text format/editor
  //  - assert the XSS-filtered values that we get from the server
  $this
    ->drupalLogin($this->privilegedUser);
  foreach ($expected as $case) {
    $this
      ->drupalGet('node/' . $case['node_id'] . '/edit');

    // Verify data- attributes.
    $dom_node = $this
      ->xpath('//textarea[@id="edit-body-0-value"]');
    $this
      ->assertIdentical(self::$sampleContent, (string) $dom_node[0]['data-editor-value-original'], 'The data-editor-value-original attribute is correctly set.');
    $this
      ->assertIdentical('false', (string) $dom_node[0]['data-editor-value-is-changed'], 'The data-editor-value-is-changed attribute is correctly set.');

    // Switch to every other text format/editor and verify the results.
    foreach ($case['switch_to'] as $format => $expected_filtered_value) {
      $this
        ->pass(format_string('Scenario: sample %sample_id, switch from %original_format to %format.', array(
        '%sample_id' => $case['node_id'],
        '%original_format' => $case['format'],
        '%format' => $format,
      )));
      $post = array(
        'value' => self::$sampleContent,
        'original_format_id' => $case['format'],
      );
      $response = $this
        ->drupalPostWithFormat('editor/filter_xss/' . $format, 'json', $post);
      $this
        ->assertResponse(200);
      $json = Json::decode($response);
      $this
        ->assertIdentical($json, $expected_filtered_value, 'The value was correctly filtered for XSS attack vectors.');
    }
  }
}