mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-10-17 18:23:19 +01:00
Compare commits
1 Commits
71006f4b65
...
613d243760
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
613d243760 |
@@ -6,10 +6,7 @@ namespace App\Exceptions;
|
||||
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
@@ -33,29 +30,6 @@ class Handler extends ExceptionHandler
|
||||
$this->reportable(function (Throwable $e): void {
|
||||
//
|
||||
});
|
||||
|
||||
// A request on an untrusted host (see App\Http\Middleware\TrustHosts)
|
||||
// otherwise renders as a bare "Bad request." 400. Show a message that
|
||||
// says how to fix it instead. The framework has already converted the
|
||||
// SuspiciousOperationException into a BadRequestHttpException by the time
|
||||
// renderables run, so we match that and inspect the original.
|
||||
$this->renderable(function (BadRequestHttpException $e, Request $request): ?Response {
|
||||
$previous = $e->getPrevious();
|
||||
|
||||
if (! $previous instanceof SuspiciousOperationException
|
||||
|| ! str_starts_with($previous->getMessage(), 'Untrusted Host')) {
|
||||
return null; // any other bad request keeps the default response
|
||||
}
|
||||
|
||||
$message = 'This hostname is not configured for this instance. '
|
||||
.'Set APP_URL, or add the host to TRUSTED_HOSTS.';
|
||||
|
||||
if ($request->expectsJson()) {
|
||||
return response()->json(['message' => $message], 400);
|
||||
}
|
||||
|
||||
return response()->view('errors.untrusted-host', ['message' => $message], 400);
|
||||
});
|
||||
}
|
||||
|
||||
public function render($request, Throwable $e): Response|RedirectResponse
|
||||
|
||||
@@ -15,7 +15,6 @@ use App\Http\Middleware\PreventRequestsDuringMaintenance;
|
||||
use App\Http\Middleware\RedirectIfAuthenticated;
|
||||
use App\Http\Middleware\ShareInertiaData;
|
||||
use App\Http\Middleware\TrimStrings;
|
||||
use App\Http\Middleware\TrustHosts;
|
||||
use App\Http\Middleware\TrustProxies;
|
||||
use App\Http\Middleware\ValidateSignature;
|
||||
use App\Http\Middleware\VerifyCsrfToken;
|
||||
@@ -48,7 +47,6 @@ class Kernel extends HttpKernel
|
||||
*/
|
||||
protected $middleware = [
|
||||
ForceHttps::class,
|
||||
TrustHosts::class,
|
||||
TrustProxies::class,
|
||||
HandleCors::class,
|
||||
PreventRequestsDuringMaintenance::class,
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Http\Middleware\TrustHosts as BaseTrustHosts;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
/**
|
||||
* Rejects requests whose Host is not trusted, preventing Host-header poisoning of
|
||||
* generated URLs (password reset, SSO callback, invitations). Trusted = the
|
||||
* APP_URL host and its subdomains, plus TRUSTED_HOSTS (for multi-host access such
|
||||
* as a Tailscale name). Health-check endpoints are exempt (probed by IP).
|
||||
*/
|
||||
class TrustHosts extends BaseTrustHosts
|
||||
{
|
||||
/**
|
||||
* @return array<int, string|null>
|
||||
*/
|
||||
public function hosts(): array
|
||||
{
|
||||
/** @var array<int, string> $configured */
|
||||
$configured = config('app.trusted_hosts', []);
|
||||
|
||||
$extra = array_map(function (string $host): string {
|
||||
$host = trim($host);
|
||||
|
||||
// "*.example.com" matches any subdomain, not the apex.
|
||||
if (str_starts_with($host, '*.')) {
|
||||
return '^.+\.'.preg_quote(substr($host, 2), '#').'$';
|
||||
}
|
||||
|
||||
return '^'.preg_quote($host, '#').'$';
|
||||
}, $configured);
|
||||
|
||||
return array_merge([$this->allSubdomainsOfApplicationUrl()], $extra);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Closure(Request): Response $next
|
||||
*/
|
||||
public function handle(Request $request, $next)
|
||||
{
|
||||
// Exempt health checks (probed by IP). Also reset the trusted hosts,
|
||||
// since Octane leaks the static state across requests.
|
||||
if ($request->is('health-check/*')) {
|
||||
Request::setTrustedHosts([]);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return parent::handle($request, $next);
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
"ext-zip": "*",
|
||||
"brick/money": "^0.10.0",
|
||||
"datomatic/laravel-enum-helper": "^2.0.0",
|
||||
"dedoc/scramble": "^0.13.39",
|
||||
"dedoc/scramble": "^0.13.36",
|
||||
"filament/filament": "^3.2",
|
||||
"flowframe/laravel-trend": "^0.5.0",
|
||||
"gotenberg/gotenberg-php": "^2.8",
|
||||
|
||||
264
composer.lock
generated
264
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "02270cef79c6a49140db75d66627b9cd",
|
||||
"content-hash": "34b85d5c7b2fe2916c70370611327926",
|
||||
"packages": [
|
||||
{
|
||||
"name": "anourvalar/eloquent-serialize",
|
||||
@@ -127,16 +127,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.391.1",
|
||||
"version": "3.390.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "90920ce5518aa864e04da0224bb0ba0ee9e31d7f"
|
||||
"reference": "a09e95bf062e15b7343f9c1362fd45c7a0dec39b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/90920ce5518aa864e04da0224bb0ba0ee9e31d7f",
|
||||
"reference": "90920ce5518aa864e04da0224bb0ba0ee9e31d7f",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a09e95bf062e15b7343f9c1362fd45c7a0dec39b",
|
||||
"reference": "a09e95bf062e15b7343f9c1362fd45c7a0dec39b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -218,9 +218,9 @@
|
||||
"support": {
|
||||
"forum": "https://github.com/aws/aws-sdk-php/discussions",
|
||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.391.1"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.390.2"
|
||||
},
|
||||
"time": "2026-08-07T20:18:18+00:00"
|
||||
"time": "2026-07-31T18:06:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -1501,16 +1501,16 @@
|
||||
},
|
||||
{
|
||||
"name": "dedoc/scramble",
|
||||
"version": "v0.13.39",
|
||||
"version": "v0.13.36",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dedoc/scramble.git",
|
||||
"reference": "7fcc4758d62f22d326637a578168bd5eb67a8625"
|
||||
"reference": "9acdb5e54f808c5bd506369f8e84322d322cc6c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dedoc/scramble/zipball/7fcc4758d62f22d326637a578168bd5eb67a8625",
|
||||
"reference": "7fcc4758d62f22d326637a578168bd5eb67a8625",
|
||||
"url": "https://api.github.com/repos/dedoc/scramble/zipball/9acdb5e54f808c5bd506369f8e84322d322cc6c9",
|
||||
"reference": "9acdb5e54f808c5bd506369f8e84322d322cc6c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1570,7 +1570,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/dedoc/scramble/issues",
|
||||
"source": "https://github.com/dedoc/scramble/tree/v0.13.39"
|
||||
"source": "https://github.com/dedoc/scramble/tree/v0.13.36"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1578,7 +1578,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-06T06:42:48+00:00"
|
||||
"time": "2026-07-27T09:42:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "defuse/php-encryption",
|
||||
@@ -3021,21 +3021,21 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "7.15.3",
|
||||
"version": "7.15.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc"
|
||||
"reference": "744101956d78b7c1384d0cbf379db13e859167bf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc",
|
||||
"reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/744101956d78b7c1384d0cbf379db13e859167bf",
|
||||
"reference": "744101956d78b7c1384d0cbf379db13e859167bf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/promises": "^2.5.2",
|
||||
"guzzlehttp/promises": "^2.5.1",
|
||||
"guzzlehttp/psr7": "^2.13",
|
||||
"php": "^7.2.5 || ^8.0",
|
||||
"psr/http-client": "^1.0",
|
||||
@@ -3129,7 +3129,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/guzzle/issues",
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.15.3"
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.15.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3145,20 +3145,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-05T19:48:21+00:00"
|
||||
"time": "2026-07-26T23:23:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"version": "2.5.2",
|
||||
"version": "2.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/promises.git",
|
||||
"reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce"
|
||||
"reference": "9ad1e4fc607446a055b95870c7f668e93b5cff29"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/2823687acff28b2dbe67b2508a6b300e2c3fa4ce",
|
||||
"reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/9ad1e4fc607446a055b95870c7f668e93b5cff29",
|
||||
"reference": "9ad1e4fc607446a055b95870c7f668e93b5cff29",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3213,7 +3213,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/promises/issues",
|
||||
"source": "https://github.com/guzzle/promises/tree/2.5.2"
|
||||
"source": "https://github.com/guzzle/promises/tree/2.5.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3229,7 +3229,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-05T19:30:54+00:00"
|
||||
"time": "2026-07-08T15:48:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
@@ -4198,16 +4198,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v12.65.0",
|
||||
"version": "v12.64.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "99a8fb3153f962a323377d6742be08da86bcccb8"
|
||||
"reference": "727a8ea2949c23ca8b5316b86a00984b6017b7a0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/99a8fb3153f962a323377d6742be08da86bcccb8",
|
||||
"reference": "99a8fb3153f962a323377d6742be08da86bcccb8",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/727a8ea2949c23ca8b5316b86a00984b6017b7a0",
|
||||
"reference": "727a8ea2949c23ca8b5316b86a00984b6017b7a0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4416,7 +4416,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2026-08-05T15:33:16+00:00"
|
||||
"time": "2026-07-14T14:25:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/octane",
|
||||
@@ -4652,16 +4652,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
"version": "v0.3.22",
|
||||
"version": "v0.3.21",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/prompts.git",
|
||||
"reference": "02b89b39e8972a998db4d5d4ad4719239dd4aee4"
|
||||
"reference": "7753c65c281c2550c7c183f14e18062073b7d821"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/prompts/zipball/02b89b39e8972a998db4d5d4ad4719239dd4aee4",
|
||||
"reference": "02b89b39e8972a998db4d5d4ad4719239dd4aee4",
|
||||
"url": "https://api.github.com/repos/laravel/prompts/zipball/7753c65c281c2550c7c183f14e18062073b7d821",
|
||||
"reference": "7753c65c281c2550c7c183f14e18062073b7d821",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4705,9 +4705,9 @@
|
||||
"description": "Add beautiful and user-friendly forms to your command-line applications.",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/prompts/issues",
|
||||
"source": "https://github.com/laravel/prompts/tree/v0.3.22"
|
||||
"source": "https://github.com/laravel/prompts/tree/v0.3.21"
|
||||
},
|
||||
"time": "2026-08-04T14:50:50+00:00"
|
||||
"time": "2026-06-26T00:11:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
@@ -4975,16 +4975,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"version": "2.9.1",
|
||||
"version": "2.8.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/commonmark.git",
|
||||
"reference": "73cb188c785abfa7a7bec73487148202968274c6"
|
||||
"reference": "1902f60f984235023acbe03db6ad614a37b3c3e7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/73cb188c785abfa7a7bec73487148202968274c6",
|
||||
"reference": "73cb188c785abfa7a7bec73487148202968274c6",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/1902f60f984235023acbe03db6ad614a37b3c3e7",
|
||||
"reference": "1902f60f984235023acbe03db6ad614a37b3c3e7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5021,7 +5021,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.10-dev"
|
||||
"dev-main": "2.9-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -5078,7 +5078,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-09T14:10:38+00:00"
|
||||
"time": "2026-07-12T15:29:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/config",
|
||||
@@ -6677,16 +6677,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "3.13.2",
|
||||
"version": "3.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/CarbonPHP/carbon.git",
|
||||
"reference": "a1c54919f5fff9800cd03c32bd01defd5a4061cb"
|
||||
"reference": "2937ad3d1d2c506fd2bc97d571438a95641f44e2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/a1c54919f5fff9800cd03c32bd01defd5a4061cb",
|
||||
"reference": "a1c54919f5fff9800cd03c32bd01defd5a4061cb",
|
||||
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/2937ad3d1d2c506fd2bc97d571438a95641f44e2",
|
||||
"reference": "2937ad3d1d2c506fd2bc97d571438a95641f44e2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6778,7 +6778,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-08T11:40:35+00:00"
|
||||
"time": "2026-07-09T18:23:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/schema",
|
||||
@@ -9799,20 +9799,20 @@
|
||||
},
|
||||
{
|
||||
"name": "spomky-labs/pki-framework",
|
||||
"version": "1.6.0",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Spomky-Labs/pki-framework.git",
|
||||
"reference": "80778a25426288acd2e3a7cde2def41a3d59cddf"
|
||||
"reference": "e0d61661962560c1cedfef02b51b431e720aae78"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/80778a25426288acd2e3a7cde2def41a3d59cddf",
|
||||
"reference": "80778a25426288acd2e3a7cde2def41a3d59cddf",
|
||||
"url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/e0d61661962560c1cedfef02b51b431e720aae78",
|
||||
"reference": "e0d61661962560c1cedfef02b51b431e720aae78",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18|^0.19",
|
||||
"brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17|^0.18",
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=8.1"
|
||||
},
|
||||
@@ -9892,7 +9892,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Spomky-Labs/pki-framework/issues",
|
||||
"source": "https://github.com/Spomky-Labs/pki-framework/tree/1.6.0"
|
||||
"source": "https://github.com/Spomky-Labs/pki-framework/tree/1.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9904,7 +9904,7 @@
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-06T16:21:11+00:00"
|
||||
"time": "2026-07-16T10:28:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "staudenmeir/eloquent-has-many-deep-contracts",
|
||||
@@ -10133,16 +10133,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.4.16",
|
||||
"version": "v7.4.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "f4c69c9aed03abf933b294257d618bdd9b30a06d"
|
||||
"reference": "088ec6fe0ef6819cbc301174093b6bfa4ad26930"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/f4c69c9aed03abf933b294257d618bdd9b30a06d",
|
||||
"reference": "f4c69c9aed03abf933b294257d618bdd9b30a06d",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/088ec6fe0ef6819cbc301174093b6bfa4ad26930",
|
||||
"reference": "088ec6fe0ef6819cbc301174093b6bfa4ad26930",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10207,7 +10207,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.4.16"
|
||||
"source": "https://github.com/symfony/console/tree/v7.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10227,7 +10227,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-07-31T12:37:14+00:00"
|
||||
"time": "2026-07-27T13:51:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
@@ -10830,16 +10830,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
"version": "v7.4.16",
|
||||
"version": "v7.4.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-foundation.git",
|
||||
"reference": "b676451bb638e99a7d34d8a2be90406822e301eb"
|
||||
"reference": "1f898ee8188adda9417fb52cf8425a8342c254e7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/b676451bb638e99a7d34d8a2be90406822e301eb",
|
||||
"reference": "b676451bb638e99a7d34d8a2be90406822e301eb",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/1f898ee8188adda9417fb52cf8425a8342c254e7",
|
||||
"reference": "1f898ee8188adda9417fb52cf8425a8342c254e7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10888,7 +10888,7 @@
|
||||
"description": "Defines an object-oriented layer for the HTTP specification",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.4.16"
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10908,20 +10908,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-07T11:50:27+00:00"
|
||||
"time": "2026-07-29T07:12:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-kernel",
|
||||
"version": "v7.4.16",
|
||||
"version": "v7.4.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-kernel.git",
|
||||
"reference": "f5e728670fa2218ae8be8ea91f2b44b7d6e5304c"
|
||||
"reference": "403275d94f94d5626c3288c599b3b48093ba24f7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/f5e728670fa2218ae8be8ea91f2b44b7d6e5304c",
|
||||
"reference": "f5e728670fa2218ae8be8ea91f2b44b7d6e5304c",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/403275d94f94d5626c3288c599b3b48093ba24f7",
|
||||
"reference": "403275d94f94d5626c3288c599b3b48093ba24f7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11007,7 +11007,7 @@
|
||||
"description": "Provides a structured process for converting a Request into a Response",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.4.16"
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11027,7 +11027,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-07T18:00:13+00:00"
|
||||
"time": "2026-07-29T11:40:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mailer",
|
||||
@@ -11115,16 +11115,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v7.4.16",
|
||||
"version": "v7.4.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mime.git",
|
||||
"reference": "20094b76a7106dbe978d31cd3bd7aa1ed248d0e5"
|
||||
"reference": "0c1daf58bc931628df0bea26840d1fc8b9a3d34b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/20094b76a7106dbe978d31cd3bd7aa1ed248d0e5",
|
||||
"reference": "20094b76a7106dbe978d31cd3bd7aa1ed248d0e5",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/0c1daf58bc931628df0bea26840d1fc8b9a3d34b",
|
||||
"reference": "0c1daf58bc931628df0bea26840d1fc8b9a3d34b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11180,7 +11180,7 @@
|
||||
"mime-type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mime/tree/v7.4.16"
|
||||
"source": "https://github.com/symfony/mime/tree/v7.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11200,7 +11200,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-07T14:56:57+00:00"
|
||||
"time": "2026-07-29T07:59:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
@@ -12258,16 +12258,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/property-access",
|
||||
"version": "v7.4.16",
|
||||
"version": "v7.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/property-access.git",
|
||||
"reference": "c3dce76a6697c6428f7d80d5cd1cf0aa5d9679f3"
|
||||
"reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/c3dce76a6697c6428f7d80d5cd1cf0aa5d9679f3",
|
||||
"reference": "c3dce76a6697c6428f7d80d5cd1cf0aa5d9679f3",
|
||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc",
|
||||
"reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12315,7 +12315,7 @@
|
||||
"reflection"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/property-access/tree/v7.4.16"
|
||||
"source": "https://github.com/symfony/property-access/tree/v7.4.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -12335,20 +12335,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-07-30T12:37:26+00:00"
|
||||
"time": "2026-03-24T13:12:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/property-info",
|
||||
"version": "v7.4.16",
|
||||
"version": "v7.4.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/property-info.git",
|
||||
"reference": "c79afdb2e720db8ee4f7050a07b3116b92cb896b"
|
||||
"reference": "fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/property-info/zipball/c79afdb2e720db8ee4f7050a07b3116b92cb896b",
|
||||
"reference": "c79afdb2e720db8ee4f7050a07b3116b92cb896b",
|
||||
"url": "https://api.github.com/repos/symfony/property-info/zipball/fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad",
|
||||
"reference": "fce3f4d9cfeb4ddc674c357b5a4c3a23ccf408ad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12405,7 +12405,7 @@
|
||||
"validator"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/property-info/tree/v7.4.16"
|
||||
"source": "https://github.com/symfony/property-info/tree/v7.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -12425,7 +12425,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-07T14:56:57+00:00"
|
||||
"time": "2026-07-28T07:09:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/psr-http-message-bridge",
|
||||
@@ -12602,16 +12602,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/serializer",
|
||||
"version": "v7.4.16",
|
||||
"version": "v7.4.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/serializer.git",
|
||||
"reference": "5ef7afacc15dfa503e9dcab7c3eda0b4460a15d9"
|
||||
"reference": "917f1575bec2853f45e012d8718f518365a9d258"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/serializer/zipball/5ef7afacc15dfa503e9dcab7c3eda0b4460a15d9",
|
||||
"reference": "5ef7afacc15dfa503e9dcab7c3eda0b4460a15d9",
|
||||
"url": "https://api.github.com/repos/symfony/serializer/zipball/917f1575bec2853f45e012d8718f518365a9d258",
|
||||
"reference": "917f1575bec2853f45e012d8718f518365a9d258",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12682,7 +12682,7 @@
|
||||
"description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/serializer/tree/v7.4.16"
|
||||
"source": "https://github.com/symfony/serializer/tree/v7.4.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -12702,7 +12702,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-06T10:16:07+00:00"
|
||||
"time": "2026-07-29T07:59:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
@@ -12884,16 +12884,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v7.4.16",
|
||||
"version": "v7.4.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "501e0ff4553c744209ca1a68790d8a4541563710"
|
||||
"reference": "a1af4dacb24eb7ef4f1ca71b94da8ddbce572281"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/501e0ff4553c744209ca1a68790d8a4541563710",
|
||||
"reference": "501e0ff4553c744209ca1a68790d8a4541563710",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/a1af4dacb24eb7ef4f1ca71b94da8ddbce572281",
|
||||
"reference": "a1af4dacb24eb7ef4f1ca71b94da8ddbce572281",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12960,7 +12960,7 @@
|
||||
"description": "Provides tools to internationalize your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation/tree/v7.4.16"
|
||||
"source": "https://github.com/symfony/translation/tree/v7.4.14"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -12980,7 +12980,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-07-30T12:37:26+00:00"
|
||||
"time": "2026-06-06T09:33:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
@@ -14385,16 +14385,16 @@
|
||||
},
|
||||
{
|
||||
"name": "fumeapp/modeltyper",
|
||||
"version": "v3.13.0",
|
||||
"version": "v3.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fumeapp/modeltyper.git",
|
||||
"reference": "f06dc8df1607cbf716d1c9d5ccef998545278012"
|
||||
"reference": "8a3e61a73a1af627bf42518fb315172ebe133fa7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fumeapp/modeltyper/zipball/f06dc8df1607cbf716d1c9d5ccef998545278012",
|
||||
"reference": "f06dc8df1607cbf716d1c9d5ccef998545278012",
|
||||
"url": "https://api.github.com/repos/fumeapp/modeltyper/zipball/8a3e61a73a1af627bf42518fb315172ebe133fa7",
|
||||
"reference": "8a3e61a73a1af627bf42518fb315172ebe133fa7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -14443,9 +14443,9 @@
|
||||
"description": "Generate TypeScript interfaces from Laravel Models",
|
||||
"support": {
|
||||
"issues": "https://github.com/fumeapp/modeltyper/issues",
|
||||
"source": "https://github.com/fumeapp/modeltyper/tree/v3.13.0"
|
||||
"source": "https://github.com/fumeapp/modeltyper/tree/v3.12.0"
|
||||
},
|
||||
"time": "2026-08-01T04:02:40+00:00"
|
||||
"time": "2026-07-28T14:20:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "hamcrest/hamcrest-php",
|
||||
@@ -14691,16 +14691,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/pint",
|
||||
"version": "v1.30.4",
|
||||
"version": "v1.30.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/pint.git",
|
||||
"reference": "a96cb6eee2961905d2fce7207aefb80945bf6b28"
|
||||
"reference": "72a0540d1aa10b6c146bda2a22f3ae003123c0ea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/a96cb6eee2961905d2fce7207aefb80945bf6b28",
|
||||
"reference": "a96cb6eee2961905d2fce7207aefb80945bf6b28",
|
||||
"url": "https://api.github.com/repos/laravel/pint/zipball/72a0540d1aa10b6c146bda2a22f3ae003123c0ea",
|
||||
"reference": "72a0540d1aa10b6c146bda2a22f3ae003123c0ea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -14712,12 +14712,12 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/semver": "^3.4.4",
|
||||
"friendsofphp/php-cs-fixer": "^3.95.18",
|
||||
"illuminate/view": "^12.65.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.95.17",
|
||||
"illuminate/view": "^12.64.0",
|
||||
"larastan/larastan": "^3.10.0",
|
||||
"laravel-zero/framework": "^12.1.0",
|
||||
"laravel/agent-detector": "^2.0.2",
|
||||
"laravel/prompts": "^0.3.22",
|
||||
"laravel/prompts": "^0.3.21",
|
||||
"mockery/mockery": "^1.6.12",
|
||||
"nunomaduro/termwind": "^2.4.0",
|
||||
"pestphp/pest": "^3.8.7"
|
||||
@@ -14757,20 +14757,20 @@
|
||||
"issues": "https://github.com/laravel/pint/issues",
|
||||
"source": "https://github.com/laravel/pint"
|
||||
},
|
||||
"time": "2026-08-05T16:47:22+00:00"
|
||||
"time": "2026-07-28T20:48:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/sail",
|
||||
"version": "v1.65.0",
|
||||
"version": "v1.64.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/sail.git",
|
||||
"reference": "d4b92139858d2a189a6302ca133e494f58afe20b"
|
||||
"reference": "08cacd3e72d6798df3fa8bd4b5d55d0f7f920625"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/sail/zipball/d4b92139858d2a189a6302ca133e494f58afe20b",
|
||||
"reference": "d4b92139858d2a189a6302ca133e494f58afe20b",
|
||||
"url": "https://api.github.com/repos/laravel/sail/zipball/08cacd3e72d6798df3fa8bd4b5d55d0f7f920625",
|
||||
"reference": "08cacd3e72d6798df3fa8bd4b5d55d0f7f920625",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -14820,7 +14820,7 @@
|
||||
"issues": "https://github.com/laravel/sail/issues",
|
||||
"source": "https://github.com/laravel/sail"
|
||||
},
|
||||
"time": "2026-08-03T18:00:17+00:00"
|
||||
"time": "2026-07-17T15:09:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/sentinel",
|
||||
@@ -14880,16 +14880,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/telescope",
|
||||
"version": "v5.22.0",
|
||||
"version": "v5.21.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/telescope.git",
|
||||
"reference": "571b08633d86086da3899474378050b16c4c6680"
|
||||
"reference": "f00f45a59843329b97aa238f28da594f3b7d4aa7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/telescope/zipball/571b08633d86086da3899474378050b16c4c6680",
|
||||
"reference": "571b08633d86086da3899474378050b16c4c6680",
|
||||
"url": "https://api.github.com/repos/laravel/telescope/zipball/f00f45a59843329b97aa238f28da594f3b7d4aa7",
|
||||
"reference": "f00f45a59843329b97aa238f28da594f3b7d4aa7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -14943,9 +14943,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/telescope/issues",
|
||||
"source": "https://github.com/laravel/telescope/tree/v5.22.0"
|
||||
"source": "https://github.com/laravel/telescope/tree/v5.21.0"
|
||||
},
|
||||
"time": "2026-07-29T14:10:20+00:00"
|
||||
"time": "2026-07-20T19:44:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
@@ -15246,11 +15246,11 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.2.8",
|
||||
"version": "2.2.7",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e285254e60f33c21902efef4a926ca0987c06804",
|
||||
"reference": "e285254e60f33c21902efef4a926ca0987c06804",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/692db47b9dddb0487934e5236e77d48594aef921",
|
||||
"reference": "692db47b9dddb0487934e5236e77d48594aef921",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -15306,7 +15306,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-08-04T22:21:45+00:00"
|
||||
"time": "2026-07-29T17:39:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
||||
@@ -75,27 +75,6 @@ return [
|
||||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Trusted Hosts
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Additional hostnames (besides the APP_URL host and its subdomains) that
|
||||
| the application is allowed to respond on. This is needed for multi-host
|
||||
| setups, e.g. reaching the instance over both a public domain and a
|
||||
| Tailscale name. A request arriving on any host that is neither APP_URL
|
||||
| (nor a subdomain of it) nor listed here is rejected, which prevents
|
||||
| Host-header poisoning of password reset and other out-of-band links.
|
||||
|
|
||||
| See App\Http\Middleware\TrustHosts.
|
||||
|
|
||||
*/
|
||||
|
||||
'trusted_hosts' => array_values(array_filter(array_map(
|
||||
'trim',
|
||||
explode(',', (string) env('TRUSTED_HOSTS', ''))
|
||||
))),
|
||||
|
||||
'asset_url' => env('ASSET_URL'),
|
||||
|
||||
'force_https' => (bool) env('APP_FORCE_HTTPS', false),
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
{{-- Self-contained on purpose: this page is rendered for a request on an
|
||||
untrusted host, so it must not call url()/route()/asset(), which would
|
||||
re-trigger Host validation and throw again. --}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Untrusted host</title>
|
||||
<style>
|
||||
html, body { height: 100%; margin: 0; }
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f5f5f5;
|
||||
color: #1f2937;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||
}
|
||||
.card {
|
||||
max-width: 32rem;
|
||||
margin: 1.5rem;
|
||||
padding: 2rem;
|
||||
background: #fff;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.75rem;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
h1 { margin: 0 0 0.75rem; font-size: 1.25rem; }
|
||||
p { margin: 0; line-height: 1.6; color: #4b5563; }
|
||||
code {
|
||||
padding: 0.1rem 0.35rem;
|
||||
background: #f3f4f6;
|
||||
border-radius: 0.25rem;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<h1>Untrusted host</h1>
|
||||
<p>
|
||||
This hostname is not configured for this instance. Set
|
||||
<code>APP_URL</code>, or add the host to <code>TRUSTED_HOSTS</code>.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,271 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Middleware;
|
||||
|
||||
use App\Http\Middleware\TrustHosts;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||
use Illuminate\Http\Request;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Tests\TestCase;
|
||||
|
||||
#[CoversClass(TrustHosts::class)]
|
||||
class TrustHostsTest extends TestCase
|
||||
{
|
||||
private const string CANONICAL = 'https://app.example.com';
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
config(['app.url' => self::CANONICAL]);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Request::setTrustedHosts([]); // don't leak static state between tests
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* The real middleware, with only the environment gate forced on (it
|
||||
* self-exempts in the testing environment).
|
||||
*/
|
||||
private function middleware(): TrustHosts
|
||||
{
|
||||
return new class($this->app) extends TrustHosts
|
||||
{
|
||||
protected function shouldSpecifyTrustedHosts(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private function accepts(Request $request): bool
|
||||
{
|
||||
$this->middleware()->handle($request, fn (Request $request): Response => new Response('passed'));
|
||||
|
||||
try {
|
||||
dump($request->getHost());
|
||||
|
||||
return true;
|
||||
} catch (\Throwable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function test_canonical_host_is_accepted(): void
|
||||
{
|
||||
// Arrange
|
||||
$request = Request::create(self::CANONICAL.'/login');
|
||||
|
||||
// Act
|
||||
$accepted = $this->accepts($request);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue($accepted);
|
||||
}
|
||||
|
||||
public function test_subdomain_of_canonical_host_is_accepted(): void
|
||||
{
|
||||
// Arrange
|
||||
$request = Request::create('https://team.app.example.com/login');
|
||||
|
||||
// Act
|
||||
$accepted = $this->accepts($request);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue($accepted);
|
||||
}
|
||||
|
||||
public function test_declared_trusted_host_is_accepted(): void
|
||||
{
|
||||
// Arrange
|
||||
config(['app.trusted_hosts' => ['box.tailnet.ts.net']]);
|
||||
$request = Request::create('https://box.tailnet.ts.net/login');
|
||||
|
||||
// Act
|
||||
$accepted = $this->accepts($request);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue($accepted);
|
||||
}
|
||||
|
||||
public function test_wildcard_trusted_host_matches_subdomains_only(): void
|
||||
{
|
||||
// Arrange
|
||||
config(['app.trusted_hosts' => ['*.example.net']]);
|
||||
$subdomainRequest = Request::create('https://foo.example.net/login');
|
||||
$nestedSubdomainRequest = Request::create('https://a.b.example.net/login');
|
||||
$apexRequest = Request::create('https://example.net/login');
|
||||
$suffixInjectionRequest = Request::create('https://example.net.evil.com/login');
|
||||
|
||||
// Act
|
||||
$subdomainAccepted = $this->accepts($subdomainRequest);
|
||||
$nestedSubdomainAccepted = $this->accepts($nestedSubdomainRequest);
|
||||
$apexAccepted = $this->accepts($apexRequest);
|
||||
$suffixInjectionAccepted = $this->accepts($suffixInjectionRequest);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue($subdomainAccepted);
|
||||
$this->assertTrue($nestedSubdomainAccepted);
|
||||
$this->assertFalse($apexAccepted);
|
||||
$this->assertFalse($suffixInjectionAccepted);
|
||||
}
|
||||
|
||||
public function test_multiple_trusted_hosts_are_all_accepted(): void
|
||||
{
|
||||
// Arrange
|
||||
config(['app.trusted_hosts' => [
|
||||
'box.tailnet.ts.net',
|
||||
'solidtime.internal',
|
||||
'*.preview.example.com',
|
||||
]]);
|
||||
$tailnetRequest = Request::create('https://box.tailnet.ts.net/login');
|
||||
$internalRequest = Request::create('https://solidtime.internal/login');
|
||||
$previewRequest = Request::create('https://pr-42.preview.example.com/login');
|
||||
$unlistedRequest = Request::create('https://evil.example.com/login');
|
||||
|
||||
// Act
|
||||
$tailnetAccepted = $this->accepts($tailnetRequest);
|
||||
$internalAccepted = $this->accepts($internalRequest);
|
||||
$previewAccepted = $this->accepts($previewRequest);
|
||||
$unlistedAccepted = $this->accepts($unlistedRequest);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue($tailnetAccepted);
|
||||
$this->assertTrue($internalAccepted);
|
||||
$this->assertTrue($previewAccepted);
|
||||
$this->assertFalse($unlistedAccepted);
|
||||
}
|
||||
|
||||
public function test_poisoned_host_is_rejected(): void
|
||||
{
|
||||
// Arrange
|
||||
$request = Request::create('https://evil.example.com/login');
|
||||
|
||||
// Act
|
||||
$accepted = $this->accepts($request);
|
||||
|
||||
// Assert
|
||||
$this->assertFalse($accepted);
|
||||
}
|
||||
|
||||
public function test_poisoned_x_forwarded_host_is_rejected(): void
|
||||
{
|
||||
// Arrange
|
||||
$request = Request::create(self::CANONICAL.'/login');
|
||||
$request->headers->set('X-Forwarded-Host', 'evil.example.com');
|
||||
$request->setTrustedProxies(
|
||||
['0.0.0.0/0', '2000::/3'],
|
||||
Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_PORT
|
||||
);
|
||||
|
||||
// Act
|
||||
$accepted = $this->accepts($request);
|
||||
|
||||
// Assert
|
||||
$this->assertFalse($accepted);
|
||||
}
|
||||
|
||||
public function test_forwarded_host_from_trusted_proxy_is_accepted(): void
|
||||
{
|
||||
// Arrange
|
||||
$request = Request::create('https://evil.example.com/login');
|
||||
$request->headers->set('X-Forwarded-Host', 'app.example.com');
|
||||
$request->setTrustedProxies(
|
||||
['0.0.0.0/0', '2000::/3'],
|
||||
Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_PORT
|
||||
);
|
||||
|
||||
// Act
|
||||
$accepted = $this->accepts($request);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue($accepted);
|
||||
}
|
||||
|
||||
public function test_forwarded_host_from_non_trusted_proxy_is_rejected_if_host_is_allowed(): void
|
||||
{
|
||||
// Arrange
|
||||
$request = Request::create('https://evil.example.com/login');
|
||||
$request->headers->set('X-Forwarded-Host', 'app.example.com');
|
||||
$request->setTrustedProxies(
|
||||
['1.2.3.4/32'], // Not a trusted proxy
|
||||
Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_PORT
|
||||
);
|
||||
|
||||
// Act
|
||||
$accepted = $this->accepts($request);
|
||||
|
||||
// Assert
|
||||
$this->assertFalse($accepted);
|
||||
}
|
||||
|
||||
public function test_health_check_endpoint_bypasses_host_validation(): void
|
||||
{
|
||||
// Arrange
|
||||
$internalIpRequest = Request::create('https://0.0.0.0/health-check/up');
|
||||
$localhostRequest = Request::create('http://localhost/health-check/up');
|
||||
|
||||
// Act
|
||||
$internalIpAccepted = $this->accepts($internalIpRequest);
|
||||
$localhostAccepted = $this->accepts($localhostRequest);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue($internalIpAccepted);
|
||||
$this->assertTrue($localhostAccepted);
|
||||
}
|
||||
|
||||
public function test_health_check_endpoint_clears_state_before_other_middleware_reads_the_host(): void
|
||||
{
|
||||
// Arrange
|
||||
Request::setTrustedHosts(['^app\.example\.com$']);
|
||||
|
||||
// Act
|
||||
$response = $this->get(self::CANONICAL.'/health-check/up', ['Host' => '0.0.0.0']);
|
||||
|
||||
// Assert
|
||||
$response->assertSuccessful()
|
||||
->assertExactJson(['success' => true]);
|
||||
}
|
||||
|
||||
public function test_untrusted_host_renders_a_helpful_error(): void
|
||||
{
|
||||
// Arrange
|
||||
$handler = app(ExceptionHandler::class);
|
||||
$exception = new SuspiciousOperationException('Untrusted Host "evil.example.com".');
|
||||
$request = Request::create('https://evil.example.com/login');
|
||||
|
||||
// Act
|
||||
$response = $handler->render($request, $exception);
|
||||
|
||||
// Assert
|
||||
$this->assertSame(400, $response->getStatusCode());
|
||||
$this->assertStringContainsString('TRUSTED_HOSTS', (string) $response->getContent());
|
||||
}
|
||||
|
||||
public function test_untrusted_host_returns_json_for_api_clients(): void
|
||||
{
|
||||
// Arrange
|
||||
$handler = app(ExceptionHandler::class);
|
||||
$exception = new SuspiciousOperationException('Untrusted Host "evil.example.com".');
|
||||
$request = Request::create('https://evil.example.com/api/v1/users');
|
||||
$request->headers->set('Accept', 'application/json');
|
||||
|
||||
// Act
|
||||
$response = $handler->render($request, $exception);
|
||||
|
||||
// Assert
|
||||
$this->assertSame(400, $response->getStatusCode());
|
||||
$this->assertJson((string) $response->getContent());
|
||||
$this->assertStringContainsString('TRUSTED_HOSTS', (string) $response->getContent());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user