CSRF Tokens not working properly

Created on 4 March 2025, about 2 months ago

Problem/Motivation

I may be missing something, but here is what I am seeing:

I have tokens enabled for all roles.

If I copy the url from a product using a logged in user, then open a new browser where Im not logged in (completely different browser, new session) and paste that url, The product is added to the cart.

This bypasses the whole point of the token, no? Any user can use any ones tokens.

Search engines could crawl these links, adding items to a cart.

Am I correct in assuming that only the current user should be able to use the link shown to them? If thats not the intended purpose, what is?

Thanks!

🐛 Bug report
Status

Active

Version

2.1

Component

Code

Created by

🇺🇸United States loze Los Angeles

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @loze
  • 🇮🇹Italy antonio.bertolini

    Similar for me...
    spider and bot crawl my product pages with add to cart link and now I've an average of 100-120 new carts by day... there's a way to add a timestamp verification inside token similar the one used by password reset?

    In my scenario commerce is used by anonymous user for create request so it's important to avoid spider crowing...

    thanks!

  • 🇮🇹Italy antonio.bertolini

    Hi all,
    I modified the functions that generate/validate the token by adding a timestamp:

      /**
       * {@inheritdoc}
       */
      public function generate(ProductVariationInterface $variation): string {
        if (!$this->needsCsrfProtection($this->currentUser)) {
          return '';
        }
        $value = $this->generateTokenValue($variation);
        return substr(Crypt::hmacBase64($value, $this->privateKey->get() . $this->getHashSalt()), 0, 16) . date('U');
      }
    
      /**
       * {@inheritdoc}
       */
      public function validate(ProductVariationInterface $variation, string $token): bool {
        if (!$this->needsCsrfProtection($this->currentUser)) {
          return TRUE;
        }
        $value = $this->generate($variation); //token+time
        $value1 = substr($value, 0, 16); //token
        $time1 = substr($value, -10); //time
    
        $token2 = substr($token, 0, 16);
        $time2 = substr($token, -10);
        
        return (hash_equals($value1, $token2) && ($time1 <($time2 + 300))); //user has 5 minutes to click the link oterwise is an expired link
        
      }
    

    in this way a user has to click 5 minutes after the page is created. This could be parameterized, in my case 5 minutes is enough...
    If the maintainers could refine my code it would be greatly appreciated!

    Thanks!!!

Production build 0.71.5 2024