Prevent cache poisoning via a Response Content-Type header
Description
In Symfony before versions 4.4.7 and 5.0.7, when a Response does not contain a Content-Type header, affected versions of Symfony can fallback to the format defined in the Accept header of the request, leading to a possible mismatch between the response's content and Content-Type header. When the response is cached, this can prevent the use of the website by other users. This has been patched in versions 4.4.7 and 5.0.7.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
symfony/http-foundationPackagist | >= 4.4.0, < 4.4.7 | 4.4.7 |
symfony/http-foundationPackagist | >= 5.0.0, < 5.0.7 | 5.0.7 |
symfony/symfonyPackagist | >= 4.4.0, < 4.4.7 | 4.4.7 |
symfony/symfonyPackagist | >= 5.0.0, < 5.0.7 | 5.0.7 |
Affected products
1- Range: >= 4.4.0 and < 4.4.7
Patches
1dca343442e6asecurity #cve-2020-5255 [HttpFoundation] Do not set the default Content-Type based on the Accept header (yceruto)
4 files changed · +26 −4
src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php+8 −1 modified@@ -12,6 +12,7 @@ namespace Symfony\Component\ErrorHandler\ErrorRenderer; use Symfony\Component\ErrorHandler\Exception\FlattenException; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Serializer\Exception\NotEncodableValueException; use Symfony\Component\Serializer\SerializerInterface; @@ -30,6 +31,7 @@ class SerializerErrorRenderer implements ErrorRendererInterface /** * @param string|callable(FlattenException) $format The format as a string or a callable that should return it + * formats not supported by Request::getMimeTypes() should be given as mime types * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it */ public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false) @@ -57,11 +59,16 @@ public function render(\Throwable $exception): FlattenException try { $format = \is_string($this->format) ? $this->format : ($this->format)($flattenException); + $headers = [ + 'Content-Type' => Request::getMimeTypes($format)[0] ?? $format, + 'Vary' => 'Accept', + ]; return $flattenException->setAsString($this->serializer->serialize($flattenException, $format, [ 'exception' => $exception, 'debug' => \is_bool($this->debug) ? $this->debug : ($this->debug)($exception), - ])); + ])) + ->setHeaders($flattenException->getHeaders() + $headers); } catch (NotEncodableValueException $e) { return $this->fallbackErrorRenderer->render($exception); }
src/Symfony/Component/HttpFoundation/Request.php+3 −1 modified@@ -1590,7 +1590,9 @@ public function isNoCache() * Gets the preferred format for the response by inspecting, in the following order: * * the request format set using setRequestFormat * * the values of the Accept HTTP header - * * the content type of the body of the request. + * + * Note that if you use this method, you should send the "Vary: Accept" header + * in the response to prevent any issues with intermediary HTTP caches. */ public function getPreferredFormat(?string $default = 'html'): ?string {
src/Symfony/Component/HttpFoundation/Response.php+1 −1 modified@@ -275,7 +275,7 @@ public function prepare(Request $request) } else { // Content-type based on the Request if (!$headers->has('Content-Type')) { - $format = $request->getPreferredFormat(null); + $format = $request->getRequestFormat(null); if (null !== $format && $mimeType = $request->getMimeType($format)) { $headers->set('Content-Type', $mimeType); }
src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php+14 −1 modified@@ -497,12 +497,25 @@ public function testPrepareDoesNothingIfRequestFormatIsNotDefined() $this->assertEquals('text/html; charset=UTF-8', $response->headers->get('content-type')); } + /** + * Same URL cannot produce different Content-Type based on the value of the Accept header, + * unless explicitly stated in the response object. + */ + public function testPrepareDoesNotSetContentTypeBasedOnRequestAcceptHeader() + { + $response = new Response('foo'); + $request = Request::create('/'); + $request->headers->set('Accept', 'application/json'); + $response->prepare($request); + + $this->assertSame('text/html; charset=UTF-8', $response->headers->get('content-type')); + } + public function testPrepareSetContentType() { $response = new Response('foo'); $request = Request::create('/'); $request->setRequestFormat('json'); - $request->headers->remove('accept'); $response->prepare($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- github.com/advisories/GHSA-mcx4-f5f5-4859ghsaADVISORY
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/C36JLPHUPKDFAX6D5WYFC4ALO2K7RDUQ/mitrevendor-advisoryx_refsource_FEDORA
- nvd.nist.gov/vuln/detail/CVE-2020-5255ghsaADVISORY
- github.com/FriendsOfPHP/security-advisories/blob/master/symfony/http-foundation/CVE-2020-5255.yamlghsaWEB
- github.com/FriendsOfPHP/security-advisories/blob/master/symfony/symfony/CVE-2020-5255.yamlghsaWEB
- github.com/symfony/symfony/commit/dca343442e6a954f96a2609e7b4e9c21ed6d74e6ghsax_refsource_MISCWEB
- github.com/symfony/symfony/security/advisories/GHSA-mcx4-f5f5-4859ghsax_refsource_CONFIRMWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/C36JLPHUPKDFAX6D5WYFC4ALO2K7RDUQghsaWEB
- symfony.com/blog/cve-2020-5255-prevent-cache-poisoning-via-a-response-content-type-headerghsax_refsource_MISCWEB
- symfony.com/cve-2020-5255ghsaWEB
News mentions
0No linked articles in our index yet.