Skip to content

Commit 6b60b88

Browse files
committed
SA-CORE-2021-006 by azinck, seanB, effulgentsia, marcoscano, larowlan, phenaproxima, xjm, mcdruid, drumm, briantschu
1 parent e536176 commit 6b60b88

File tree

5 files changed

+59
-24
lines changed

5 files changed

+59
-24
lines changed

modules/media/js/plugins/drupalmedia/plugin.es6.js

+3
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,9 @@
472472
uuid: this.data.attributes['data-entity-uuid'],
473473
},
474474
dataType: 'html',
475+
headers: {
476+
'X-Drupal-MediaPreview-CSRF-Token': editor.config.drupalMedia_previewCsrfToken,
477+
},
475478
success: (previewHtml, textStatus, jqXhr) => {
476479
this.element.setHtml(previewHtml);
477480
this.setData(

modules/media/js/plugins/drupalmedia/plugin.js

+3
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,9 @@
314314
uuid: this.data.attributes['data-entity-uuid']
315315
},
316316
dataType: 'html',
317+
headers: {
318+
'X-Drupal-MediaPreview-CSRF-Token': editor.config.drupalMedia_previewCsrfToken
319+
},
317320
success: function success(previewHtml, textStatus, jqXhr) {
318321
_this3.element.setHtml(previewHtml);
319322
_this3.setData('label', jqXhr.getResponseHeader('Drupal-Media-Label'));

modules/media/src/Controller/MediaFilterController.php

+30
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
use Drupal\Core\Entity\ContentEntityStorageInterface;
88
use Drupal\Core\Entity\EntityRepositoryInterface;
99
use Drupal\Core\Render\RendererInterface;
10+
use Drupal\Core\Session\AccountInterface;
1011
use Drupal\filter\FilterFormatInterface;
1112
use Symfony\Component\DependencyInjection\ContainerInterface;
1213
use Symfony\Component\HttpFoundation\Request;
1314
use Symfony\Component\HttpFoundation\Response;
15+
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
1416
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
1517

1618
/**
@@ -93,6 +95,8 @@ public static function create(ContainerInterface $container) {
9395
* @see \Drupal\editor\EditorController::getUntransformedText
9496
*/
9597
public function preview(Request $request, FilterFormatInterface $filter_format) {
98+
self::checkCsrf($request, \Drupal::currentUser());
99+
96100
$text = $request->query->get('text');
97101
$uuid = $request->query->get('uuid');
98102
if ($text == '' || $uuid == '') {
@@ -140,4 +144,30 @@ public static function formatUsesMediaEmbedFilter(FilterFormatInterface $filter_
140144
->addCacheableDependency($filter_format);
141145
}
142146

147+
/**
148+
* Throws an AccessDeniedHttpException if the request fails CSRF validation.
149+
*
150+
* This is used instead of \Drupal\Core\Access\CsrfAccessCheck, in order to
151+
* allow access for anonymous users.
152+
*
153+
* @todo Refactor this to an access checker.
154+
*/
155+
private static function checkCsrf(Request $request, AccountInterface $account) {
156+
$header = 'X-Drupal-MediaPreview-CSRF-Token';
157+
158+
if (!$request->headers->has($header)) {
159+
throw new AccessDeniedHttpException();
160+
}
161+
if ($account->isAnonymous()) {
162+
// For anonymous users, just the presence of the custom header is
163+
// sufficient protection.
164+
return;
165+
}
166+
// For authenticated users, validate the token value.
167+
$token = $request->headers->get($header);
168+
if (!\Drupal::csrfToken()->validate($token, $header)) {
169+
throw new AccessDeniedHttpException();
170+
}
171+
}
172+
143173
}

modules/media/src/Plugin/CKEditorPlugin/DrupalMedia.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ public function getFile() {
9898
* {@inheritdoc}
9999
*/
100100
public function getConfig(Editor $editor) {
101-
return [];
101+
return [
102+
'drupalMedia_previewCsrfToken' => \Drupal::csrfToken()->get('X-Drupal-MediaPreview-CSRF-Token'),
103+
];
102104
}
103105

104106
/**

modules/media/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php

+20-23
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Drupal\Tests\media\FunctionalJavascript;
44

55
use Drupal\Component\Utility\Html;
6-
use Drupal\Core\Url;
76
use Drupal\editor\Entity\Editor;
87
use Drupal\field\Entity\FieldConfig;
98
use Drupal\file\Entity\File;
@@ -1027,14 +1026,13 @@ public function linkabilityProvider() {
10271026
* @dataProvider previewAccessProvider
10281027
*/
10291028
public function testEmbedPreviewAccess($media_embed_enabled, $can_use_format) {
1030-
$format = FilterFormat::create([
1031-
'format' => $this->randomMachineName(),
1032-
'name' => $this->randomString(),
1033-
'filters' => [
1034-
'filter_align' => ['status' => TRUE],
1035-
'filter_caption' => ['status' => TRUE],
1036-
'media_embed' => ['status' => $media_embed_enabled],
1037-
],
1029+
// Reconfigure the host entity's text format to suit our needs.
1030+
/** @var \Drupal\filter\FilterFormatInterface $format */
1031+
$format = FilterFormat::load($this->host->body->format);
1032+
$format->set('filters', [
1033+
'filter_align' => ['status' => TRUE],
1034+
'filter_caption' => ['status' => TRUE],
1035+
'media_embed' => ['status' => $media_embed_enabled],
10381036
]);
10391037
$format->save();
10401038

@@ -1045,24 +1043,23 @@ public function testEmbedPreviewAccess($media_embed_enabled, $can_use_format) {
10451043
$permissions[] = $format->getPermissionName();
10461044
}
10471045
$this->drupalLogin($this->drupalCreateUser($permissions));
1048-
1049-
$text = '<drupal-media data-caption="baz" data-entity-type="media" data-entity-uuid="' . $this->media->uuid() . '"></drupal-media>';
1050-
$route_parameters = ['filter_format' => $format->id()];
1051-
$options = [
1052-
'query' => [
1053-
'text' => $text,
1054-
'uuid' => $this->media->uuid(),
1055-
],
1056-
];
1057-
$this->drupalGet(Url::fromRoute('media.filter.preview', $route_parameters, $options));
1046+
$this->drupalGet($this->host->toUrl('edit-form'));
10581047

10591048
$assert_session = $this->assertSession();
1060-
if ($media_embed_enabled && $can_use_format) {
1061-
$assert_session->elementExists('css', 'img');
1062-
$assert_session->responseContains('baz');
1049+
if ($can_use_format) {
1050+
$this->waitForEditor();
1051+
$this->assignNameToCkeditorIframe();
1052+
$this->getSession()->switchToIFrame('ckeditor');
1053+
if ($media_embed_enabled) {
1054+
$this->assertNotEmpty($assert_session->waitForElementVisible('css', 'article.media'));
1055+
}
1056+
else {
1057+
$assert_session->assertWaitOnAjaxRequest();
1058+
$assert_session->elementNotExists('css', 'article.media');
1059+
}
10631060
}
10641061
else {
1065-
$assert_session->responseContains('You are not authorized to access this page.');
1062+
$assert_session->pageTextContains('This field has been disabled because you do not have sufficient permissions to edit it.');
10661063
}
10671064
}
10681065

0 commit comments

Comments
 (0)