Skip to content

Commit d9910e0

Browse files
committed
security #cve-2020-15094 Remove headers with internal meaning from HttpClient responses (mpdude)
This PR was merged into the 4.4 branch.
2 parents bca14aa + ba39753 commit d9910e0

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

src/Symfony/Component/HttpClient/Tests/CachingHttpClientTest.php

+68
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\HttpClient\MockHttpClient;
1717
use Symfony\Component\HttpClient\Response\MockResponse;
1818
use Symfony\Component\HttpKernel\HttpCache\Store;
19+
use Symfony\Contracts\HttpClient\ResponseInterface;
1920

2021
class CachingHttpClientTest extends TestCase
2122
{
@@ -39,4 +40,71 @@ public function testRequestHeaders()
3940
self::assertSame($response->getRequestOptions()['normalized_headers']['application-name'][0], 'Application-Name: test1234');
4041
self::assertSame($response->getRequestOptions()['normalized_headers']['test-name-header'][0], 'Test-Name-Header: test12345');
4142
}
43+
44+
public function testDoesNotEvaluateResponseBody()
45+
{
46+
$body = file_get_contents(__DIR__.'/Fixtures/assertion_failure.php');
47+
$response = $this->runRequest(new MockResponse($body, ['response_headers' => ['X-Body-Eval' => true]]));
48+
$headers = $response->getHeaders();
49+
50+
$this->assertSame($body, $response->getContent());
51+
$this->assertArrayNotHasKey('x-body-eval', $headers);
52+
}
53+
54+
public function testDoesNotIncludeFile()
55+
{
56+
$file = __DIR__.'/Fixtures/assertion_failure.php';
57+
58+
$response = $this->runRequest(new MockResponse(
59+
'test', ['response_headers' => [
60+
'X-Body-Eval' => true,
61+
'X-Body-File' => $file,
62+
]]
63+
));
64+
$headers = $response->getHeaders();
65+
66+
$this->assertSame('test', $response->getContent());
67+
$this->assertArrayNotHasKey('x-body-eval', $headers);
68+
$this->assertArrayNotHasKey('x-body-file', $headers);
69+
}
70+
71+
public function testDoesNotReadFile()
72+
{
73+
$file = __DIR__.'/Fixtures/assertion_failure.php';
74+
75+
$response = $this->runRequest(new MockResponse(
76+
'test', ['response_headers' => [
77+
'X-Body-File' => $file,
78+
]]
79+
));
80+
$headers = $response->getHeaders();
81+
82+
$this->assertSame('test', $response->getContent());
83+
$this->assertArrayNotHasKey('x-body-file', $headers);
84+
}
85+
86+
public function testRemovesXContentDigest()
87+
{
88+
$response = $this->runRequest(new MockResponse(
89+
'test', [
90+
'response_headers' => [
91+
'X-Content-Digest' => 'some-hash',
92+
]
93+
]));
94+
$headers = $response->getHeaders();
95+
96+
$this->assertArrayNotHasKey('x-content-digest', $headers);
97+
}
98+
99+
private function runRequest(MockResponse $mockResponse): ResponseInterface
100+
{
101+
$mockClient = new MockHttpClient($mockResponse);
102+
103+
$store = new Store(sys_get_temp_dir() . '/sf_http_cache');
104+
$client = new CachingHttpClient($mockClient, $store);
105+
106+
$response = $client->request('GET', 'http://test');
107+
108+
return $response;
109+
}
42110
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
throw new \PHPUnit\Framework\AssertionFailedError('Response body should not be evaluated.');

src/Symfony/Component/HttpKernel/HttpClientKernel.php

+4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
5858

5959
$response = new Response($response->getContent(!$catch), $response->getStatusCode(), $response->getHeaders(!$catch));
6060

61+
$response->headers->remove('X-Body-File');
62+
$response->headers->remove('X-Body-Eval');
63+
$response->headers->remove('X-Content-Digest');
64+
6165
$response->headers = new class($response->headers->all()) extends ResponseHeaderBag {
6266
protected function computeCacheControlValue(): string
6367
{

0 commit comments

Comments
 (0)