mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-13 20:14:45 +00:00
fix: sanitize error output in server validation logs
Escape dynamic error messages with htmlspecialchars() before concatenating into HTML strings stored in validation_logs. Add a Purify-based mutator on Server model as defense-in-depth, with a dedicated HTMLPurifier config that allows only safe structural tags. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
e39678aea5
commit
103d5b6c06
7 files changed
+102
-5
No files matched your search
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$user = User::factory()->create();
|
||||
$this->team = Team::factory()->create();
|
||||
$user->teams()->attach($this->team);
|
||||
$this->actingAs($user);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
$this->server = Server::factory()->create([
|
||||
'team_id' => $this->team->id,
|
||||
]);
|
||||
});
|
||||
|
||||
it('strips dangerous HTML from validation_logs via mutator', function () {
|
||||
$xssPayload = '<img src=x onerror=alert(document.domain)>';
|
||||
$this->server->update(['validation_logs' => $xssPayload]);
|
||||
$this->server->refresh();
|
||||
|
||||
expect($this->server->validation_logs)->not->toContain('<img')
|
||||
->and($this->server->validation_logs)->not->toContain('onerror');
|
||||
});
|
||||
|
||||
it('strips script tags from validation_logs', function () {
|
||||
$xssPayload = '<script>alert("xss")</script>';
|
||||
$this->server->update(['validation_logs' => $xssPayload]);
|
||||
$this->server->refresh();
|
||||
|
||||
expect($this->server->validation_logs)->not->toContain('<script');
|
||||
});
|
||||
|
||||
it('preserves allowed HTML in validation_logs', function () {
|
||||
$allowedHtml = 'Server is not reachable.<br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs">documentation</a> for further help.<br><br><div class="text-error">Error: Connection refused</div>';
|
||||
$this->server->update(['validation_logs' => $allowedHtml]);
|
||||
$this->server->refresh();
|
||||
|
||||
expect($this->server->validation_logs)->toContain('<a')
|
||||
->and($this->server->validation_logs)->toContain('<br')
|
||||
->and($this->server->validation_logs)->toContain('<div')
|
||||
->and($this->server->validation_logs)->toContain('Connection refused');
|
||||
});
|
||||
|
||||
it('allows null validation_logs', function () {
|
||||
$this->server->update(['validation_logs' => null]);
|
||||
$this->server->refresh();
|
||||
|
||||
expect($this->server->validation_logs)->toBeNull();
|
||||
});
|
||||
|
||||
it('sanitizes XSS embedded within valid error HTML', function () {
|
||||
$maliciousError = 'Server is not reachable.<br><div class="text-error">Error: <img src=x onerror=alert(document.cookie)></div>';
|
||||
$this->server->update(['validation_logs' => $maliciousError]);
|
||||
$this->server->refresh();
|
||||
|
||||
expect($this->server->validation_logs)->toContain('<div')
|
||||
->and($this->server->validation_logs)->toContain('Error:')
|
||||
->and($this->server->validation_logs)->not->toContain('onerror')
|
||||
->and($this->server->validation_logs)->not->toContain('<img');
|
||||
});
|
||||
|
||||
it('sanitizes event handler attributes in validation_logs', function () {
|
||||
$payload = '<div onmouseover="alert(1)" class="text-error">Error</div>';
|
||||
$this->server->update(['validation_logs' => $payload]);
|
||||
$this->server->refresh();
|
||||
|
||||
expect($this->server->validation_logs)->toContain('<div')
|
||||
->and($this->server->validation_logs)->not->toContain('onmouseover');
|
||||
});
|
||||
Reference in new issue
Block a user