Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

脆弱性対応(4.2) #6254

Merged
merged 13 commits into from
Jul 29, 2024
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eccube",
"version": "4.2.3",
"version": "4.2.3-p1",
"description": "EC-CUBE EC open platform.",
"main": "index.js",
"directories": {
Expand Down
2 changes: 1 addition & 1 deletion src/Eccube/Common/Constant.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Constant
/**
* EC-CUBE VERSION.
*/
public const VERSION = '4.2.3';
public const VERSION = '4.2.3-p1';

/**
* Enable value.
Expand Down
95 changes: 82 additions & 13 deletions src/Eccube/Controller/Admin/Store/OwnerStoreController.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validator\ValidatorInterface;

/**
* @Route("/%eccube_admin_route%/store/plugin/api")
Expand All @@ -48,6 +50,11 @@ class OwnerStoreController extends AbstractController
*/
protected $pluginService;

/**
* @var ValidatorInterface
*/
protected ValidatorInterface $validator;

/**
* @var ComposerServiceInterface
*/
Expand Down Expand Up @@ -81,6 +88,7 @@ class OwnerStoreController extends AbstractController
* @param PluginApiService $pluginApiService
* @param BaseInfoRepository $baseInfoRepository
* @param CacheUtil $cacheUtil
* @param ValidatorInterface $validatorInterface
*
* @throws \Doctrine\ORM\NoResultException
* @throws \Doctrine\ORM\NonUniqueResultException
Expand All @@ -92,14 +100,16 @@ public function __construct(
SystemService $systemService,
PluginApiService $pluginApiService,
BaseInfoRepository $baseInfoRepository,
CacheUtil $cacheUtil
CacheUtil $cacheUtil,
ValidatorInterface $validatorInterface
) {
$this->pluginRepository = $pluginRepository;
$this->pluginService = $pluginService;
$this->systemService = $systemService;
$this->pluginApiService = $pluginApiService;
$this->BaseInfo = $baseInfoRepository->get();
$this->cacheUtil = $cacheUtil;
$this->validator = $validatorInterface;

// TODO: Check the flow of the composer service below
$this->composerService = $composerService;
Expand Down Expand Up @@ -263,13 +273,32 @@ public function apiInstall(Request $request)

$pluginCode = $request->get('pluginCode');

try {
$log = $this->composerService->execRequire('ec-cube/'.$pluginCode);
$errors = $this->validator->validate(
$pluginCode,
[
new Assert\NotBlank(),
new Assert\Regex(
[
'pattern' => '/^[a-zA-Z0-9_]+$/',
]
),
]
);

if ($errors->count() != 0) {
$log = [];
foreach ($errors as $error) {
$log[] = $error->getMessage();
}
} else {
try {
$log = $this->composerService->execRequire('ec-cube/'.$pluginCode);

return $this->json(['success' => true, 'log' => $log]);
} catch (\Exception $e) {
$log = $e->getMessage();
log_error($e);
return $this->json(['success' => true, 'log' => $log]);
} catch (\Exception $e) {
$log = $e->getMessage();
log_error($e);
}
}

return $this->json(['success' => false, 'log' => $log], 500);
Expand Down Expand Up @@ -343,13 +372,53 @@ public function apiUpgrade(Request $request)
$pluginCode = $request->get('pluginCode');
$version = $request->get('version');

try {
$log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
$log = [];

$errors = $this->validator->validate(
$pluginCode,
[
new Assert\NotBlank(),
new Assert\Regex(
[
'pattern' => '/^[a-zA-Z0-9_]+$/',
]
),
]
);

if ($errors->count() != 0) {
foreach ($errors as $error) {
$log[] = $error->getMessage();
}
}

return $this->json(['success' => true, 'log' => $log]);
} catch (\Exception $e) {
$log = $e->getMessage();
log_error($e);
$errors = $this->validator->validate(
$version,
[
new Assert\NotBlank(),
new Assert\Regex(
[
'pattern' => '/^[0-9.]+$/',
]
),
]
);

if ($errors->count() != 0) {
foreach ($errors as $error) {
$log[] = $error->getMessage();
}
}

if (empty($log)) {
try {
$log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);

return $this->json(['success' => true, 'log' => $log]);
} catch (\Exception $e) {
$log = $e->getMessage();
log_error($e);
}
}

return $this->json(['success' => false, 'log' => $log], 500);
Expand Down
11 changes: 6 additions & 5 deletions tests/Eccube/Tests/Fixture/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Service\PurchaseFlow\PurchaseFlow;
use Eccube\Util\StringUtil;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

/**
Expand Down Expand Up @@ -412,11 +413,11 @@ public function createProduct($product_name = null, $product_class_num = 3, $wit
for ($i = 0; $i < 3; $i++) {
$ProductImage = new ProductImage();
if ($with_image) {
$width = $faker->numberBetween(480, 640);
$height = $faker->numberBetween(480, 640);
$image = $faker->uuid.'.jpg';
$src = file_get_contents('https://placekitten.com/'.$width.'/'.$height);
file_put_contents(__DIR__.'/../../../../html/upload/save_image/'.$image, $src);
$image = $faker->uuid.'.png';
$src = __DIR__.'/../../../../html/upload/save_image/no_image_product.png';
$dist = __DIR__.'/../../../../html/upload/save_image/'.$image;
$fs = new Filesystem();
$fs->copy($src, $dist);
} else {
$image = $faker->word.'.jpg';
}
Expand Down
81 changes: 81 additions & 0 deletions tests/Eccube/Tests/Web/Admin/Store/PluginControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,85 @@ public function testSubmit()
$this->actual = $this->entityManager->getRepository(\Eccube\Entity\BaseInfo::class)->get()->getPhpPath();
$this->verify();
}

/**
* 異常系を確認。正常系のインストールはE2Eテストの方で実施
*
* @dataProvider OwnerStoreInstallParam
*
*/
public function testFailureInstall($param1, $param2, $message)
{
$form = [
'pluginCode' => $param1,
'version' => $param2,
];

$crawler = $this->client->request('POST',
$this->generateUrl('admin_store_plugin_api_install', $form),
[],
[],
[
'HTTP_X-Requested-With' => 'XMLHttpRequest',
'CONTENT_TYPE' => 'application/json',
]
);
// ダウンロードできないことを確認
$this->assertEquals(500, $this->client->getResponse()->getStatusCode());
// ログを確認
$this->assertContains($message, json_decode($this->client->getResponse()->getContent())->log);
}

/**
* 異常系を確認。正常系のアップデートはE2Eテストの方で実施
*
* @dataProvider OwnerStoreUpgradeParam
*
*/
public function testFailureUpgrade($param1, $param2, $message)
{
$form = [
'pluginCode' => $param1,
'version' => $param2,
];

$crawler = $this->client->request('POST',
$this->generateUrl('admin_store_plugin_api_upgrade', $form),
[],
[],
[
'HTTP_X-Requested-With' => 'XMLHttpRequest',
'CONTENT_TYPE' => 'application/json',
]
);
// ダウンロードできないことを確認
$this->assertEquals(500, $this->client->getResponse()->getStatusCode());

// ログを確認
$this->assertStringContainsString($message, implode(',', json_decode($this->client->getResponse()->getContent())->log));
}

/**
* 異常系のテストケース
*/
public function OwnerStoreInstallParam()
{
return [
['api42+symfony/yaml:5.3', '4.3.0', '有効な値ではありません。'],
['', '4.3.0','入力されていません。'],
];
}

/**
* 異常系のテストケース
*/
public function OwnerStoreUpgradeParam()
{
return [
['api42+symfony/yaml:5.3', '4.3.0', '有効な値ではありません。'],
['api42', '4.3.0 symfony/yaml:5.3', '有効な値ではありません。'],
['api42', '','入力されていません。'],
['', '4.3.0','入力されていません。'],
];
}
}
Loading