Tests für Upload und Ui, strengere CI-Prüfungen
- tests/UploadTest.php prüft den SVG-Filter (Skripte, Event-Handler, javascript:-Verweise) und Upload::isLocal gegen Pfad-Tricks - tests/UiTest.php prüft Versionsstempel, Media-Pfade und die Branding-Overrides inklusive Abweisung ungültiger Farbwerte - PHPStan analysiert jetzt auch includes/Ui.php und includes/Upload.php - CI vergleicht die Sprachdateien (gleiche Schlüsselmenge) und prüft, dass jeder im Code verwendete Schlüssel existiert Dabei aufgefallen und behoben: Upload.php rief __() direkt auf und wäre außerhalb einer Seite mit geladener I18n mit einem Fatal Error abgebrochen; jetzt gibt es einen Fallback auf die deutsche Meldung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
36e06ac817
commit
0716311ff6
5 changed files with 220 additions and 10 deletions
72
tests/UploadTest.php
Normal file
72
tests/UploadTest.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ReflectionMethod;
|
||||
use RuntimeException;
|
||||
|
||||
require_once __DIR__ . '/../includes/Upload.php';
|
||||
|
||||
/**
|
||||
* Der SVG-Filter ist die sicherheitskritische Stelle beim Bild-Upload:
|
||||
* hochgeladene Grafiken werden aus der eigenen Domain ausgeliefert, aktive
|
||||
* Inhalte darin waeren damit gespeichertes XSS.
|
||||
*/
|
||||
class UploadTest extends TestCase
|
||||
{
|
||||
private function sanitize(string $svg): string
|
||||
{
|
||||
$method = new ReflectionMethod(\Upload::class, 'sanitizeSvg');
|
||||
$method->setAccessible(true);
|
||||
|
||||
return $method->invoke(null, $svg);
|
||||
}
|
||||
|
||||
public function testRemovesScriptElement(): void
|
||||
{
|
||||
$clean = $this->sanitize('<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script><rect/></svg>');
|
||||
|
||||
$this->assertStringNotContainsString('<script', $clean);
|
||||
$this->assertStringNotContainsString('alert(1)', $clean);
|
||||
$this->assertStringContainsString('<rect/>', $clean);
|
||||
}
|
||||
|
||||
public function testRemovesEventHandlers(): void
|
||||
{
|
||||
$clean = $this->sanitize('<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"><rect onclick=\'steal()\'/></svg>');
|
||||
|
||||
$this->assertStringNotContainsString('onload', $clean);
|
||||
$this->assertStringNotContainsString('onclick', $clean);
|
||||
}
|
||||
|
||||
public function testRemovesJavascriptLinks(): void
|
||||
{
|
||||
$clean = $this->sanitize('<svg xmlns="http://www.w3.org/2000/svg"><a xlink:href="javascript:alert(1)">x</a></svg>');
|
||||
|
||||
$this->assertStringNotContainsString('javascript:', $clean);
|
||||
}
|
||||
|
||||
public function testKeepsHarmlessMarkup(): void
|
||||
{
|
||||
$svg = '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><circle cx="5" cy="5" r="4" fill="#0f766e"/></svg>';
|
||||
|
||||
$this->assertSame($svg, $this->sanitize($svg));
|
||||
}
|
||||
|
||||
public function testRejectsNonSvgContent(): void
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->sanitize('GIF89a<html>');
|
||||
}
|
||||
|
||||
public function testIsLocalOnlyAcceptsUploadPaths(): void
|
||||
{
|
||||
$this->assertTrue(\Upload::isLocal('uploads/abc.png'));
|
||||
$this->assertFalse(\Upload::isLocal('https://example.com/logo.png'));
|
||||
$this->assertFalse(\Upload::isLocal('uploads/../config.php'));
|
||||
$this->assertFalse(\Upload::isLocal(''));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue