Skip to content

Commit

Permalink
Fix MIME detection vulnerability
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasbestle committed Jul 26, 2023
1 parent a1e0f81 commit 2f06ba1
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 2 deletions.
12 changes: 12 additions & 0 deletions src/Http/Response.php
Expand Up @@ -176,6 +176,18 @@ public static function file(string $file, array $props = []): static
'type' => F::extensionToMime(F::extension($file))
], $props);

// if we couldn't serve a correct MIME type, force
// the browser to display the file as plain text to
// harden against attacks from malicious file uploads
if ($props['type'] === null) {
if (isset($props['headers']) !== true) {
$props['headers'] = [];
}

$props['type'] = 'text/plain';
$props['headers']['X-Content-Type-Options'] = 'nosniff';
}

return new static($props);
}

Expand Down
33 changes: 31 additions & 2 deletions tests/Http/ResponseTest.php
Expand Up @@ -188,13 +188,41 @@ public function testJsonWithPrettyArray()

public function testFile()
{
$file = __DIR__ . '/fixtures/download.txt';
$file = __DIR__ . '/fixtures/download.json';

$response = Response::file($file);

$this->assertSame('application/json', $response->type());
$this->assertSame(200, $response->code());
$this->assertSame('{"foo": "bar"}', $response->body());

$response = Response::file($file, [
'code' => '201',
'headers' => [
'Pragma' => 'no-cache'
]
]);

$this->assertSame('application/json', $response->type());
$this->assertSame(201, $response->code());
$this->assertSame('{"foo": "bar"}', $response->body());
$this->assertSame([
'Pragma' => 'no-cache'
], $response->headers());
}

public function testFileInvalid()
{
$file = __DIR__ . '/fixtures/download.xyz';

$response = Response::file($file);

$this->assertSame('text/plain', $response->type());
$this->assertSame(200, $response->code());
$this->assertSame('test', $response->body());
$this->assertSame([
'X-Content-Type-Options' => 'nosniff',
], $response->headers());

$response = Response::file($file, [
'code' => '201',
Expand All @@ -207,7 +235,8 @@ public function testFile()
$this->assertSame(201, $response->code());
$this->assertSame('test', $response->body());
$this->assertSame([
'Pragma' => 'no-cache'
'Pragma' => 'no-cache',
'X-Content-Type-Options' => 'nosniff',
], $response->headers());
}

Expand Down
1 change: 1 addition & 0 deletions tests/Http/fixtures/download.json
@@ -0,0 +1 @@
{"foo": "bar"}
File renamed without changes.

0 comments on commit 2f06ba1

Please sign in to comment.