Skip to content

Commit

Permalink
Security changes from upstream 2.4.7-p3
Browse files Browse the repository at this point in the history
  • Loading branch information
magento packaging service authored and rhoerr committed Oct 8, 2024
1 parent acd6ffc commit c6a4f4f
Show file tree
Hide file tree
Showing 189 changed files with 7,957 additions and 529 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\AdminNotification\Block\Grid\MassAction;

use Magento\AdminNotification\Controller\Adminhtml\Notification\MarkAsRead;
use Magento\Backend\Block\Widget\Grid\Massaction\VisibilityCheckerInterface;
use Magento\Framework\AuthorizationInterface;

/**
* Class checks if mark as read action can be displayed on massaction list
*/
class MarkAsReadVisibility implements VisibilityCheckerInterface
{
/**
* @var AuthorizationInterface
*/
private $authorization;

/**
* @param AuthorizationInterface $authorizationInterface
*/
public function __construct(AuthorizationInterface $authorizationInterface)
{
$this->authorization = $authorizationInterface;
}

/**
* @inheritdoc
*/
public function isVisible()
{
return $this->authorization->isAllowed(MarkAsRead::ADMIN_RESOURCE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\AdminNotification\Block\Grid\MassAction;

use Magento\AdminNotification\Controller\Adminhtml\Notification\Remove;
use Magento\Backend\Block\Widget\Grid\Massaction\VisibilityCheckerInterface;
use Magento\Framework\AuthorizationInterface;

/**
* Class checks if remove action can be displayed on massaction list
*/
class RemoveVisibility implements VisibilityCheckerInterface
{
/**
* @var AuthorizationInterface
*/
private $authorization;

/**
* @param AuthorizationInterface $authorizationInterface
*/
public function __construct(AuthorizationInterface $authorizationInterface)
{
$this->authorization = $authorizationInterface;
}

/**
* @inheritdoc
*/
public function isVisible()
{
return $this->authorization->isAllowed(Remove::ADMIN_RESOURCE);
}
}
53 changes: 30 additions & 23 deletions app/code/Magento/AdminNotification/Block/Grid/Renderer/Actions.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
<?php
declare(strict_types=1);

/**
* Adminhtml AdminNotification Severity Renderer
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\AdminNotification\Block\Grid\Renderer;

use Magento\AdminNotification\Controller\Adminhtml\Notification\MarkAsRead;
use Magento\AdminNotification\Controller\Adminhtml\Notification\Remove;
use Magento\Backend\Block\Context;
use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\App\ActionInterface;
Expand Down Expand Up @@ -45,33 +44,41 @@ public function __construct(Context $context, Data $urlHelper, array $data = [])
*/
public function render(DataObject $row)
{
$readDetailsHtml = $row->getUrl() ? '<a class="action-details" target="_blank" href="' .
$readDetailsHtml = $row->getUrl() ?
'<a class="action-details" target="_blank" href="' .
$this->escapeUrl($row->getUrl())
. '">' .
__('Read Details') . '</a>' : '';

$markAsReadHtml = !$row->getIsRead() ? '<a class="action-mark" href="' . $this->getUrl(
'*/*/markAsRead/',
['_current' => true, 'id' => $row->getNotificationId()]
) . '">' . __(
'Mark as Read'
) . '</a>' : '';
$markAsReadHtml = !$row->getIsRead()
&& $this->_authorization->isAllowed(MarkAsRead::ADMIN_RESOURCE) ?
'<a class="action-mark" href="' . $this->escapeUrl($this->getUrl(
'*/*/markAsRead/',
['_current' => true, 'id' => $row->getNotificationId()]
)) . '">' . __(
'Mark as Read'
) . '</a>' : '';

$removeUrl = $this->getUrl(
'*/*/remove/',
[
'_current' => true,
'id' => $row->getNotificationId(),
ActionInterface::PARAM_NAME_URL_ENCODED => $this->_urlHelper->getEncodedUrl()
]
);

$removeHtml = $this->_authorization->isAllowed(Remove::ADMIN_RESOURCE) ?
'<a class="action-delete" href="'
. $this->escapeUrl($removeUrl)
.'" onClick="deleteConfirm('. __('\'Are you sure?\'') .', this.href); return false;">'
. __('Remove') . '</a>' : '';

$encodedUrl = $this->_urlHelper->getEncodedUrl();
return sprintf(
'%s%s<a class="action-delete" href="%s" onClick="deleteConfirm(\'%s\', this.href); return false;">%s</a>',
'%s%s%s',
$readDetailsHtml,
$markAsReadHtml,
$this->getUrl(
'*/*/remove/',
[
'_current' => true,
'id' => $row->getNotificationId(),
ActionInterface::PARAM_NAME_URL_ENCODED => $encodedUrl
]
),
__('Are you sure?'),
__('Remove')
$removeHtml,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\AdminNotification\Controller\Adminhtml\Notification;

use Magento\AdminNotification\Controller\Adminhtml\Notification;
Expand All @@ -16,6 +18,13 @@
*/
class AjaxMarkAsRead extends Notification implements HttpPostActionInterface
{
/**
* Authorization level of a basic admin session
*
* @see _isAllowed()
*/
public const ADMIN_RESOURCE = 'Magento_AdminNotification::mark_as_read';

/**
* @var NotificationService
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Magento\AdminNotification\Block\Grid\Renderer\Actions;
use Magento\Backend\Block\Context;
use Magento\Framework\DataObject;
use Magento\Framework\AuthorizationInterface;
use Magento\Framework\Escaper;
use Magento\Framework\Url\Helper\Data;
use Magento\Framework\UrlInterface;
Expand All @@ -35,16 +36,23 @@ protected function setUp(): void

/** @var Escaper|MockObject $escaperMock */
$escaperMock = $this->createMock(Escaper::class);
$escaperMock->expects($this->once())->method('escapeUrl')->willReturn('https://magento.com');
$escaperMock->expects($this->atLeastOnce())->method('escapeUrl')->willReturn('https://magento.com');

/** @var AuthorizationInterface|MockObject $authorizationMock */
$authorizationMock = $this->getMockForAbstractClass(AuthorizationInterface::class);
$authorizationMock->expects($this->atLeastOnce())
->method('isAllowed')
->willReturn(true);

/** @var UrlInterface|MockObject $urlBuilder */
$urlBuilder = $this->getMockForAbstractClass(UrlInterface::class);
$urlBuilder->expects($this->once())->method('getUrl')->willReturn('http://magento.com');

/** @var Context|MockObject $contextMock */
$contextMock = $this->createMock(Context::class);
$contextMock->expects($this->once())->method('getEscaper')->willReturn($escaperMock);
$contextMock->expects($this->atLeastOnce())->method('getEscaper')->willReturn($escaperMock);
$contextMock->expects($this->once())->method('getUrlBuilder')->willReturn($urlBuilder);
$contextMock->expects($this->once())->method('getAuthorization')->willReturn($authorizationMock);

/** @var Data|MockObject $urlHelperMock */
$urlHelperMock = $this->createMock(Data::class);
Expand All @@ -65,7 +73,7 @@ public function testShouldRenderMessageWhenUrlIsGiven() : void
// Ignoring Code Style at this point due to the long HEREDOC
// phpcs:disable
$expected = <<<HTML
<a class="action-details" target="_blank" href="https://magento.com">Read Details</a><a class="action-delete" href="http://magento.com" onClick="deleteConfirm('Are you sure?', this.href); return false;">Remove</a>
<a class="action-details" target="_blank" href="https://magento.com">Read Details</a><a class="action-delete" href="https://magento.com" onClick="deleteConfirm('Are you sure?', this.href); return false;">Remove</a>
HTML;
// phpcs:enable

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@
<item name="mark_as_read" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Mark as Read</item>
<item name="url" xsi:type="string">*/*/massMarkAsRead</item>
<item name="visible" xsi:type="object">Magento\AdminNotification\Block\Grid\MassAction\MarkAsReadVisibility</item>
</item>
<item name="remove" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Remove</item>
<item name="url" xsi:type="string">*/*/massRemove</item>
<item name="confirm" xsi:type="string" translate="true">Are you sure?</item>
<item name="visible" xsi:type="object">Magento\AdminNotification\Block\Grid\MassAction\RemoveVisibility</item>
</item>
</argument>
</arguments>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,27 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\AdvancedSearch\Controller\Adminhtml\Search\System\Config;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\AdvancedSearch\Model\Client\ClientResolver;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filter\StripTags;

class TestConnection extends Action
class TestConnection extends Action implements HttpPostActionInterface
{
/**
* Authorization level of a basic admin session.
*
* @see _isAllowed()
*/
const ADMIN_RESOURCE = 'Magento_CatalogSearch::config_catalog_search';
public const ADMIN_RESOURCE = 'Magento_Catalog::config_catalog';

/**
* @var ClientResolver
Expand Down Expand Up @@ -57,7 +62,7 @@ public function __construct(
/**
* Check for connection to server
*
* @return \Magento\Framework\Controller\Result\Json
* @return Json
*/
public function execute()
{
Expand All @@ -69,22 +74,22 @@ public function execute()

try {
if (empty($options['engine'])) {
throw new \Magento\Framework\Exception\LocalizedException(
throw new LocalizedException(
__('Missing search engine parameter.')
);
}
$response = $this->clientResolver->create($options['engine'], $options)->testConnection();
if ($response) {
$result['success'] = true;
}
} catch (\Magento\Framework\Exception\LocalizedException $e) {
} catch (LocalizedException $e) {
$result['errorMessage'] = $e->getMessage();
} catch (\Exception $e) {
$message = __($e->getMessage());
$result['errorMessage'] = $this->tagFilter->filter($message);
}

/** @var \Magento\Framework\Controller\Result\Json $resultJson */
/** @var Json $resultJson */
$resultJson = $this->resultJsonFactory->create();
return $resultJson->setData($result);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ abstract class Design extends Action
*
* @see _isAllowed()
*/
const ADMIN_RESOURCE = 'Magento_Backend::design';
public const ADMIN_RESOURCE = 'Magento_Backend::schedule';

/**
* Core registry
* Core registry instance
*
* @var \Magento\Framework\Registry
*/
Expand Down
17 changes: 16 additions & 1 deletion app/code/Magento/CatalogImportExport/Model/Import/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ class Product extends AbstractEntity
private const COL_NAME_FORMAT = '/[\x00-\x1F\x7F]/';
public const CONFIG_KEY_PRODUCT_TYPES = 'global/importexport/import_product_types';

/**
* Filter chain const
*/
private const FILTER_CHAIN = "php://filter";

/**
* Size of bunch - part of products to save in one step.
*/
Expand Down Expand Up @@ -775,6 +780,11 @@ class Product extends AbstractEntity
*/
private ?SkuStorage $skuStorage;

/**
* @var File|null
*/
private ?File $fileDriver;

/**
* @param \Magento\Framework\Json\Helper\Data $jsonHelper
* @param \Magento\ImportExport\Helper\Data $importExportData
Expand Down Expand Up @@ -950,6 +960,8 @@ public function __construct(
->get(ProductRepositoryInterface::class);
$this->stockItemProcessor = $stockItemProcessor ?? ObjectManager::getInstance()
->get(StockItemProcessorInterface::class);
$this->fileDriver = $fileDriver ?? ObjectManager::getInstance()
->get(File::class);
}

/**
Expand Down Expand Up @@ -2126,7 +2138,10 @@ private function getRemoteFileContent(string $filename): string
{
try {
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$content = file_get_contents($filename);
if (stripos($filename, self::FILTER_CHAIN) !== false) {
return '';
}
$content = $this->fileDriver->fileGetContents($filename);
} catch (\Exception $e) {
$content = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
*/
class Validator extends AbstractValidator implements RowValidatorInterface
{
/**
* Filter chain const
*/
private const FILTER_CHAIN = "php://filter";

/**
* @var RowValidatorInterface[]|AbstractValidator[]
*/
Expand Down Expand Up @@ -82,6 +87,10 @@ public function __construct(
protected function textValidation($attrCode, $type)
{
$val = $this->string->cleanString($this->_rowData[$attrCode]);
if (stripos($val, self::FILTER_CHAIN) !== false) {
$this->_addMessages([RowValidatorInterface::ERROR_INVALID_ATTRIBUTE_TYPE]);
return false;
}
if ($type == 'text') {
$valid = $this->string->strlen($val) < Product::DB_MAX_TEXT_LENGTH;
} elseif ($attrCode == Product::COL_SKU) {
Expand Down
Loading

0 comments on commit c6a4f4f

Please sign in to comment.