VYPR
High severityNVD Advisory· Published Mar 30, 2020· Updated Aug 4, 2024

Firewall configured with unanimous strategy was not actually unanimous in symfony/security-http

CVE-2020-5275

Description

In symfony/security-http before versions 4.4.7 and 5.0.7, when a Firewall checks access control rule, it iterate overs each rule's attributes and stops as soon as the accessDecisionManager decides to grant access on the attribute, preventing the check of next attributes that should have been take into account in an unanimous strategy. The accessDecisionManager is now called with all attributes at once, allowing the unanimous strategy being applied on each attribute. This issue is patched in versions 4.4.7 and 5.0.7.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
symfony/securityPackagist
>= 4.4.0, < 4.4.74.4.7
symfony/securityPackagist
>= 5.0.0, < 5.0.75.0.7
symfony/security-httpPackagist
>= 4.4.0, < 4.4.74.4.7
symfony/security-httpPackagist
>= 5.0.0, < 5.0.75.0.7
symfony/symfonyPackagist
>= 4.4.0, < 4.4.74.4.7
symfony/symfonyPackagist
>= 5.0.0, < 5.0.75.0.7

Affected products

1

Patches

1
c935e4a3fba6

security #cve-2020-5275 [Security] Fix access_control behavior with unanimous decision strategy (chalasr)

https://github.com/symfony/symfonyNicolas GrekasMar 30, 2020via ghsa
4 files changed · +50 12
  • src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php+7 2 modified
    @@ -53,11 +53,16 @@ public function __construct(iterable $voters = [], string $strategy = self::STRA
         }
     
         /**
    +     * @param bool $allowMultipleAttributes Whether to allow passing multiple values to the $attributes array
    +     *
          * {@inheritdoc}
          */
    -    public function decide(TokenInterface $token, array $attributes, $object = null)
    +    public function decide(TokenInterface $token, array $attributes, $object = null/*, bool $allowMultipleAttributes = false*/)
         {
    -        if (\count($attributes) > 1) {
    +        $allowMultipleAttributes =  3 < func_num_args() && func_get_arg(3);
    +
    +        // Special case for AccessListener, do not remove the right side of the condition before 6.0
    +        if (\count($attributes) > 1 && !$allowMultipleAttributes) {
                 @trigger_error(sprintf('Passing more than one Security attribute to "%s()" is deprecated since Symfony 4.4. Use multiple "decide()" calls or the expression language (e.g. "is_granted(...) or is_granted(...)") instead.', __METHOD__), E_USER_DEPRECATED);
             }
     
    
  • src/Symfony/Component/Security/Http/composer.json+1 1 modified
    @@ -17,7 +17,7 @@
         ],
         "require": {
             "php": "^7.1.3",
    -        "symfony/security-core": "^4.4",
    +        "symfony/security-core": "^4.4.7",
             "symfony/http-foundation": "^3.4.40|^4.4.7|^5.0.7",
             "symfony/http-kernel": "^4.4",
             "symfony/property-access": "^3.4|^4.0|^5.0"
    
  • src/Symfony/Component/Security/Http/Firewall/AccessListener.php+1 9 modified
    @@ -87,15 +87,7 @@ public function authenticate(RequestEvent $event)
                 $this->tokenStorage->setToken($token);
             }
     
    -        $granted = false;
    -        foreach ($attributes as $key => $value) {
    -            if ($this->accessDecisionManager->decide($token, [$key => $value], $request)) {
    -                $granted = true;
    -                break;
    -            }
    -        }
    -
    -        if (!$granted) {
    +        if (!$this->accessDecisionManager->decide($token, $attributes, $request, true)) {
                 $exception = new AccessDeniedException();
                 $exception->setAttributes($attributes);
                 $exception->setSubject($request);
    
  • src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php+41 0 modified
    @@ -16,6 +16,7 @@
     use Symfony\Component\HttpKernel\Event\RequestEvent;
     use Symfony\Component\HttpKernel\HttpKernelInterface;
     use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
    +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
     use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
     use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
     use Symfony\Component\Security\Http\AccessMapInterface;
    @@ -227,4 +228,44 @@ public function testHandleWhenTheSecurityTokenStorageHasNoToken()
     
             $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST));
         }
    +
    +    public function testHandleMWithultipleAttributesShouldBeHandledAsAnd()
    +    {
    +        $request = new Request();
    +
    +        $accessMap = $this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock();
    +        $accessMap
    +            ->expects($this->any())
    +            ->method('getPatterns')
    +            ->with($this->equalTo($request))
    +            ->willReturn([['foo' => 'bar', 'bar' => 'baz'], null])
    +        ;
    +
    +        $authenticatedToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
    +        $authenticatedToken
    +            ->expects($this->any())
    +            ->method('isAuthenticated')
    +            ->willReturn(true)
    +        ;
    +
    +        $tokenStorage = new TokenStorage();
    +        $tokenStorage->setToken($authenticatedToken);
    +
    +        $accessDecisionManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')->getMock();
    +        $accessDecisionManager
    +            ->expects($this->once())
    +            ->method('decide')
    +            ->with($this->equalTo($authenticatedToken), $this->equalTo(['foo' => 'bar', 'bar' => 'baz']), $this->equalTo($request), true)
    +            ->willReturn(true)
    +        ;
    +
    +        $listener = new AccessListener(
    +            $tokenStorage,
    +            $accessDecisionManager,
    +            $accessMap,
    +            $this->createMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')
    +        );
    +
    +        $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST));
    +    }
     }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

10

News mentions

0

No linked articles in our index yet.