Skip to content

Commit f6ef7cd

Browse files
fix: validates custom provided policies (#3254)
* fix: validates custom provided policies Validates any customer provided json policy document for CloudFront\Signer.php to avoid any non allowed symbols. * chore: add changelog entry
1 parent d300ec1 commit f6ef7cd

3 files changed

Lines changed: 67 additions & 0 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"type": "enhancement",
4+
"category": "",
5+
"description": "Add a validation for custom policies to make sure the property `Resource` has not a non allowed character."
6+
}
7+
]

src/CloudFront/Signer.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public function getSignature($resource = null, $expires = null, $policy = null)
8181
$signatureHash = [];
8282
if ($policy) {
8383
$policy = preg_replace('/\s/s', '', $policy);
84+
self::validatePolicy($policy);
8485
$signatureHash['Policy'] = $this->encode($policy);
8586
} elseif ($resource && $expires) {
8687
$expires = (int) $expires; // Handle epoch passed as string
@@ -136,4 +137,35 @@ private function encode($policy)
136137
{
137138
return strtr(base64_encode($policy), '+=/', '-_~');
138139
}
140+
141+
/**
142+
* Validates a customer provided json document.
143+
*
144+
* @param string $jsonPolicy
145+
*
146+
* @return void
147+
*/
148+
private static function validatePolicy(string $jsonPolicy): void
149+
{
150+
$policy = json_decode($jsonPolicy, true);
151+
foreach ($policy['Statement'] ?? [] as $statement) {
152+
if (isset($statement['Resource'])) {
153+
self::validateResourceUrl($statement['Resource']);
154+
}
155+
}
156+
}
157+
158+
/**
159+
* @param string $url
160+
*
161+
* @return void
162+
*/
163+
private static function validateResourceUrl(string $url): void
164+
{
165+
if (preg_match('/["\\\\\x00-\x1F]/', $url)) {
166+
throw new \InvalidArgumentException(
167+
'URL contains invalid characters: ", \\, or control characters'
168+
);
169+
}
170+
}
139171
}

tests/CloudFront/SignerTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,34 @@ public function cannedPolicyParameterProvider()
173173
];
174174
}
175175

176+
/**
177+
* @dataProvider invalidResourceUrlProvider
178+
*/
179+
public function testValidatesCustomPolicy(string $resourceUrl)
180+
{
181+
$this->expectException(\InvalidArgumentException::class);
182+
$this->expectExceptionMessage('URL contains invalid characters: ", \\, or control characters');
183+
$policy = json_encode([
184+
'Statement' => [
185+
['Resource' => $resourceUrl]
186+
]
187+
], JSON_UNESCAPED_SLASHES);
188+
$this->instance->getSignature(null, null, $policy);
189+
}
190+
191+
public static function invalidResourceUrlProvider(): array
192+
{
193+
return [
194+
'json_injection' => ["https://example.com/file\",\"Resource\":\"*\",\"x\":\""],
195+
'double_quote' => ['test"invalid.mp4'],
196+
'backslash' => ['test\\invalid.mp4'],
197+
'newline' => ["test\ninvalid.mp4"],
198+
'carriage_return' => ["test\rinvalid.mp4"],
199+
'null_byte' => ["test\x00invalid.mp4"],
200+
'tab' => ["test\tinvalid.mp4"],
201+
];
202+
}
203+
176204
private function getCustomPolicy()
177205
{
178206
return json_encode([

0 commit comments

Comments
 (0)