Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7e2abc6

Browse files
committed
Allow custom scheme to be used as redirection URIs and additional security means
1 parent b4128fd commit 7e2abc6

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

src/Symfony/Component/Security/Http/HttpUtils.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,20 @@ public function checkRequestPath(Request $request, string $path)
148148
*/
149149
public function generateUri(Request $request, string $path)
150150
{
151-
if (str_starts_with($path, 'http') || !$path) {
151+
$url = parse_url($path);
152+
153+
// Prevent path traversal (ex: https://example.com/../../file)
154+
if (preg_match('#/\.\.?(/|$)#', $url['path'])) {
155+
return $request->getUriForPath('/');
156+
}
157+
158+
// Prevent protocol-relative redirection (ex: //example.com/file)
159+
if (!isset($url['scheme']) && isset($url['host'], $url['path'])) {
160+
return $request->getUriForPath('/');
161+
}
162+
163+
// absolute URL
164+
if (isset($url['scheme'], $url['host'])) {
152165
return $path;
153166
}
154167

src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,54 @@ public function testCreateRedirectResponseWithRequestsDomain()
5858
$this->assertTrue($response->isRedirect('http://localhost/blog'));
5959
}
6060

61+
/**
62+
* @dataProvider validRequestDomainUrls
63+
*/
64+
public function testCreateRedirectResponse(?string $domainRegexp, string $path, string $expectedRedirectUri)
65+
{
66+
$utils = new HttpUtils($this->getUrlGenerator(), null, $domainRegexp);
67+
$response = $utils->createRedirectResponse($this->getRequest(), $path);
68+
69+
$this->assertTrue($response->isRedirect($expectedRedirectUri));
70+
$this->assertEquals(302, $response->getStatusCode());
71+
}
72+
73+
public static function validRequestDomainUrls()
74+
{
75+
return [
76+
'/foobar' => [
77+
null,
78+
'/foobar',
79+
'http://localhost/foobar',
80+
],
81+
'http://symfony.com/ without domain regex' => [
82+
null,
83+
'http://symfony.com/',
84+
'http://symfony.com/',
85+
],
86+
'http://localhost/blog with #^https?://symfony\.com$#i' => [
87+
'#^https?://symfony\.com$#i',
88+
'http://symfony.com/blog',
89+
'http://symfony.com/blog',
90+
],
91+
'http://localhost/blog with #^https?://%s$#i' => [
92+
'#^https?://%s$#i',
93+
'http://localhost/blog',
94+
'http://localhost/blog',
95+
],
96+
'custom scheme' => [
97+
null,
98+
'android-app://com.google.android.gm/',
99+
'android-app://com.google.android.gm/',
100+
],
101+
'custom scheme with all URL components' => [
102+
null,
103+
'android-app://foo:[email protected]:8080/software/index.html?lite=true#section1',
104+
'android-app://foo:[email protected]:8080/software/index.html?lite=true#section1',
105+
],
106+
];
107+
}
108+
61109
/**
62110
* @dataProvider badRequestDomainUrls
63111
*/
@@ -77,6 +125,9 @@ public static function badRequestDomainUrls()
77125
['http:/\\pirate.net/foo'],
78126
['http:\\/pirate.net/foo'],
79127
['http://////pirate.net/foo'],
128+
['//evil.com/do-bad-things'],
129+
['http://localhost/foo/../bar'],
130+
['http:///foo'],
80131
];
81132
}
82133

0 commit comments

Comments
 (0)