Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# WIP Release notes for Commerce 5.6

- Cart controller actions that accept an explicit cart number are now rate limited to mitigate enumeration attacks.
- Cart numbers are now generated using a cryptographically secure random number generator.
- Fixed a bug where Variant with empty SKUs didn't show a validation error when saving a product after it was duplicated. ([#4197](https://github.com/craftcms/commerce/issues/4197))
- Shipping rule categories are now eager loaded on shipping rules automatically. ([#4220](https://github.com/craftcms/commerce/issues/4220))
- Added `craft\commerce\services\ShippingRuleCategories::getShippingRuleCategoriesByRuleIds()`.
Expand Down
42 changes: 41 additions & 1 deletion src/controllers/CartController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
use craft\elements\User;
use craft\errors\ElementNotFoundException;
use craft\errors\MissingComponentException;
use craft\helpers\Json;
use craft\helpers\StringHelper;
use craft\helpers\UrlHelper;
use Illuminate\Support\Collection;
use thamtech\ratelimiter\Context;
use thamtech\ratelimiter\handlers\TooManyRequestsHttpExceptionHandler;
use thamtech\ratelimiter\limit\RateLimit;
use thamtech\ratelimiter\RateLimiter;
use Throwable;
use yii\base\Exception;
use yii\base\InvalidConfigException;
Expand Down Expand Up @@ -76,6 +79,43 @@ public function init(): void
parent::init();
}

/**
* @inheritdoc
*/
public function behaviors(): array
{
return parent::behaviors() + [
'rateLimiter' => [
'class' => RateLimiter::class,
'only' => ['get-cart', 'update-cart', 'load-cart', 'complete'],
'components' => [
'rateLimit' => [
'definitions' => [
'cart-by-number' => [
'class' => RateLimit::class,
'limit' => 1,
'window' => 1,
// Only apply rate limiting when a cart number is explicitly passed
'active' => function(Context $context, $rateLimitId) {
return $context->request->getBodyParam('number') || $context->request->getQueryParam('number');
},
'identifier' => fn(Context $context, $rateLimitId) => sprintf(
'%s:%s',
$rateLimitId,
$context->request->getUserIP(),
),
],
],
],
'allowanceStorage' => [
'cache' => 'cache',
],
],
'as tooManyRequestsException' => TooManyRequestsHttpExceptionHandler::class,
],
];
}

/**
* Returns the cart as JSON
*
Expand Down
2 changes: 1 addition & 1 deletion src/services/Carts.php
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ public function forgetCart(): void
*/
public function generateCartNumber(): string
{
return md5(uniqid((string)mt_rand(), true));
return bin2hex(random_bytes(16));
}

/**
Expand Down
Loading