fix(security): validate application domains safely

Use shared domain validation and normalization for application, service, and
preview domains so unsafe host input is rejected consistently.

Cover command-substitution payloads in application domain tests.
This commit is contained in:
Andras Bacsai committed 2026-07-02 17:47:04 +02:00
1 parent cc4f666ba2
commit c6c7ec1c31
6 files changed
+72 -38

No files matched your search

@@ -3,6 +3,7 @@
namespace App\Livewire\Project\Application;
use App\Models\ApplicationPreview;
use App\Support\ValidationPatterns;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Component;
use Spatie\Url\Url;
@@ -33,6 +34,11 @@ class PreviewsCompose extends Component
{
try {
$this->authorize('update', $this->preview->application);
$this->validate([
'domain' => ValidationPatterns::applicationDomainRules(),
]);
$this->domain = ValidationPatterns::normalizeApplicationDomains($this->domain);
$docker_compose_domains = data_get($this->preview, 'docker_compose_domains');
$docker_compose_domains = json_decode($docker_compose_domains, true) ?: [];
@@ -73,9 +79,13 @@ class PreviewsCompose extends Component
$preview_fqdn = str_replace('{{pr_id}}', $this->preview->pull_request_id, $preview_fqdn);
$preview_fqdn = str($generated_fqdn)->before('://').'://'.$preview_fqdn;
} else {
foreach (ValidationPatterns::validateApplicationDomains($domain_string) as $error) {
throw new \InvalidArgumentException($error);
}
// Use the existing domain from the main application
// Handle multiple domains separated by commas
$domain_list = explode(',', $domain_string);
$domain_list = ValidationPatterns::applicationDomainList($domain_string);
$preview_fqdns = [];
$template = $this->preview->application->preview_url_template;
$random = new_public_id();