Skip to content

Commit 01864ed

Browse files
committed
feature #49193 [Security] Return 403 instead of 500 when no firewall is defined (nicolas-grekas)
This PR was merged into the 6.3 branch. Discussion ---------- [Security] Return 403 instead of 500 when no firewall is defined | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | #34148 | License | MIT | Doc PR | - Looks like ranting on Twitter may pay of sometimes ;) https://twitter.com/zodman/status/1620954291187097600 The changes on ErrorListener make `#[WithHttpStatus]` and `#[WithLogLevel]` propagate to child classes. Best reviewed [ignoring white spaces](https://github.com/symfony/symfony/pull/49193/files?w=1). Commits ------- c021ce7 [Security] Return 403 instead of 500 when no firewall is defined
2 parents e474b76 + c021ce7 commit 01864ed

File tree

5 files changed

+35
-14
lines changed

5 files changed

+35
-14
lines changed

src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,17 @@ public function logKernelException(ExceptionEvent $event)
7171
// There's no specific status code defined in the configuration for this exception
7272
if (!$throwable instanceof HttpExceptionInterface) {
7373
$class = new \ReflectionClass($throwable);
74-
$attributes = $class->getAttributes(WithHttpStatus::class, \ReflectionAttribute::IS_INSTANCEOF);
7574

76-
if ($attributes) {
77-
/** @var WithHttpStatus $instance */
78-
$instance = $attributes[0]->newInstance();
75+
do {
76+
if ($attributes = $class->getAttributes(WithHttpStatus::class, \ReflectionAttribute::IS_INSTANCEOF)) {
77+
/** @var WithHttpStatus $instance */
78+
$instance = $attributes[0]->newInstance();
7979

80-
$throwable = new HttpException($instance->statusCode, $throwable->getMessage(), $throwable, $instance->headers);
81-
$event->setThrowable($throwable);
82-
}
80+
$throwable = new HttpException($instance->statusCode, $throwable->getMessage(), $throwable, $instance->headers);
81+
$event->setThrowable($throwable);
82+
break;
83+
}
84+
} while ($class = $class->getParentClass());
8385
}
8486

8587
$e = FlattenException::createFromThrowable($throwable);
@@ -185,14 +187,16 @@ private function resolveLogLevel(\Throwable $throwable): string
185187
}
186188
}
187189

188-
$attributes = (new \ReflectionClass($throwable))->getAttributes(WithLogLevel::class);
190+
$class = new \ReflectionClass($throwable);
189191

190-
if ($attributes) {
191-
/** @var WithLogLevel $instance */
192-
$instance = $attributes[0]->newInstance();
192+
do {
193+
if ($attributes = $class->getAttributes(WithLogLevel::class)) {
194+
/** @var WithLogLevel $instance */
195+
$instance = $attributes[0]->newInstance();
193196

194-
return $instance->level;
195-
}
197+
return $instance->level;
198+
}
199+
} while ($class = $class->getParentClass());
196200

197201
if (!$throwable instanceof HttpExceptionInterface || $throwable->getStatusCode() >= 500) {
198202
return LogLevel::CRITICAL;

src/Symfony/Component/HttpKernel/Tests/EventListener/ErrorListenerTest.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public function testHandleWithLoggerAndCustomConfiguration()
123123
public function testHandleWithLogLevelAttribute()
124124
{
125125
$request = new Request();
126-
$event = new ExceptionEvent(new TestKernel(), $request, HttpKernelInterface::MAIN_REQUEST, new WarningWithLogLevelAttribute());
126+
$event = new ExceptionEvent(new TestKernel(), $request, HttpKernelInterface::MAIN_REQUEST, new ChildOfWarningWithLogLevelAttribute());
127127
$logger = new TestLogger();
128128
$l = new ErrorListener('not used', $logger);
129129

@@ -280,6 +280,7 @@ public static function exceptionWithAttributeProvider()
280280
{
281281
yield [new WithCustomUserProvidedAttribute(), 208, ['name' => 'value']];
282282
yield [new WithGeneralAttribute(), 412, ['some' => 'thing']];
283+
yield [new ChildOfWithGeneralAttribute(), 412, ['some' => 'thing']];
283284
}
284285
}
285286

@@ -341,7 +342,15 @@ class WithGeneralAttribute extends \Exception
341342
{
342343
}
343344

345+
class ChildOfWithGeneralAttribute extends WithGeneralAttribute
346+
{
347+
}
348+
344349
#[WithLogLevel(LogLevel::WARNING)]
345350
class WarningWithLogLevelAttribute extends \Exception
346351
{
347352
}
353+
354+
class ChildOfWarningWithLogLevelAttribute extends WarningWithLogLevelAttribute
355+
{
356+
}

src/Symfony/Component/Security/Core/Exception/AccessDeniedException.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111

1212
namespace Symfony\Component\Security\Core\Exception;
1313

14+
use Symfony\Component\HttpKernel\Attribute\WithHttpStatus;
15+
1416
/**
1517
* AccessDeniedException is thrown when the account has not the required role.
1618
*
1719
* @author Fabien Potencier <fabien@symfony.com>
1820
*/
21+
#[WithHttpStatus(403)]
1922
class AccessDeniedException extends RuntimeException
2023
{
2124
private array $attributes = [];

src/Symfony/Component/Security/Core/Exception/AuthenticationException.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Security\Core\Exception;
1313

14+
use Symfony\Component\HttpKernel\Attribute\WithHttpStatus;
1415
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
1516

1617
/**
@@ -19,6 +20,7 @@
1920
* @author Fabien Potencier <fabien@symfony.com>
2021
* @author Alexander <iam.asm89@gmail.com>
2122
*/
23+
#[WithHttpStatus(401)]
2224
class AuthenticationException extends RuntimeException
2325
{
2426
/** @internal */

src/Symfony/Component/Security/Http/EntryPoint/Exception/NotAnEntryPointException.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@
1111

1212
namespace Symfony\Component\Security\Http\EntryPoint\Exception;
1313

14+
use Symfony\Component\HttpKernel\Attribute\WithHttpStatus;
15+
1416
/**
1517
* Thrown by generic decorators when a decorated authenticator does not implement
1618
* {@see AuthenticationEntryPointInterface}.
1719
*
1820
* @author Robin Chalas <robin.chalas@gmail.com>
1921
*/
22+
#[WithHttpStatus(401)]
2023
class NotAnEntryPointException extends \RuntimeException
2124
{
2225
}

0 commit comments

Comments
 (0)