Composer-Sicherheitsupdates, dompdf 3, email-Regel ohne Zeilenumbrueche
- Patch-/Minor-Updates (guzzle, commonmark, flysystem, excel, phpspreadsheet, phpseclib, laravel/framework 11.x) - barryvdh/laravel-dompdf 3.1 (dompdf 3.1.6), Test fuer den PDF-Weg inkl. eingebettetem PHP und Briefpapier - Rueckport des Laravel-12.60-Fixes gegen CRLF in der email-Regel - Protokoll: Ergebnis composer audit, offene Punkte Laravel 12 und PDF-Seitenzahlen Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
47a46b1401
commit
4274bff9e2
7 changed files with 669 additions and 491 deletions
|
|
@ -7,6 +7,7 @@ use App\Services\Payment\Payone\PayonePaymentService;
|
|||
use App\Services\Payment\Stripe\StripeClientWrapper;
|
||||
use App\Services\Util;
|
||||
use App\Support\OperationalAlert;
|
||||
use App\Support\Validation\Validator as SafeEmailValidator;
|
||||
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
|
||||
use Illuminate\Foundation\Console\AboutCommand;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
|
|
@ -14,6 +15,7 @@ use Illuminate\Queue\Events\JobFailed;
|
|||
use Illuminate\Support\Facades\Queue;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
|
|
@ -26,6 +28,7 @@ class AppServiceProvider extends ServiceProvider
|
|||
public function boot()
|
||||
{
|
||||
Schema::defaultStringLength(191);
|
||||
Validator::resolver(fn ($translator, $data, $rules, $messages, $attributes) => new SafeEmailValidator($translator, $data, $rules, $messages, $attributes));
|
||||
Paginator::defaultView('pagination::bootstrap-4');
|
||||
Paginator::defaultSimpleView('pagination::simple-bootstrap-4');
|
||||
|
||||
|
|
|
|||
30
app/Support/Validation/Validator.php
Normal file
30
app/Support/Validation/Validator.php
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Support\Validation;
|
||||
|
||||
use Illuminate\Validation\Validator as BaseValidator;
|
||||
|
||||
/**
|
||||
* Rückportierter Sicherheitsfix aus Laravel 12.60 (GHSA-5vg9-5847-vvmq):
|
||||
* Die email-Regel lässt in Laravel 11 Zeilenumbrüche zu, über die sich
|
||||
* Mail-Header einschleusen lassen. Nach dem Update auf Laravel 12 entfernen
|
||||
* (samt Registrierung in AppServiceProvider).
|
||||
*/
|
||||
class Validator extends BaseValidator
|
||||
{
|
||||
/**
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @param array<int, string> $parameters
|
||||
*/
|
||||
public function validateEmail($attribute, $value, $parameters): bool
|
||||
{
|
||||
if (is_string($value) || (is_object($value) && method_exists($value, '__toString'))) {
|
||||
if (preg_match('/[\r\n]/', (string) $value) > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::validateEmail($attribute, $value, $parameters);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"barryvdh/laravel-dompdf": "^2.2",
|
||||
"barryvdh/laravel-dompdf": "^3.1",
|
||||
"cocur/slugify": "^4.5",
|
||||
"cviebrock/eloquent-sluggable": "^11.0",
|
||||
"doctrine/dbal": "^3.6.0|^4.0",
|
||||
|
|
|
|||
1001
composer.lock
generated
1001
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -26,6 +26,7 @@
|
|||
| `v1.2.1` | bereinigte Git-Historie (alle Hashes neu), IDE-Helper-Dateien nicht mehr versioniert |
|
||||
| `v1.2.2` | `deploy.sh` nur bei `APP_ENV=production`, `dev/app-bak` entfernt |
|
||||
| `v1.3.0` | GlitchTip (Server, Fehlersignale, Browser), `sentry/sentry-laravel`; Tests ohne lokalen Datei-Cache |
|
||||
| `v1.4.0` | Composer-Sicherheitsupdates, dompdf 3, `email`-Regel lehnt Zeilenumbrüche ab |
|
||||
|
||||
Alle Tags vor dem 08.10. wurden beim Bereinigen der Historie neu erzeugt; Commit-Hashes in älteren
|
||||
Notizen unter `dev/` gehören zur alten Historie.
|
||||
|
|
@ -76,8 +77,32 @@ sind die alten Objekte (`.env`, Schlüssel, 10-GB-Datei) auch auf den Git-Server
|
|||
`emails/exception.blade.php` prüfen, ob sonst noch genutzt. Betriebs-Alarme (`OperationalAlert`) bleiben.
|
||||
- **Datenschutzerklärung**: Fehlerprotokollierung aufnehmen (User-ID, URL, Browser, Fehlermeldung;
|
||||
eigener Server; Frist = Aufbewahrung in GlitchTip; berechtigtes Interesse) — neue Erklärung ist in Arbeit.
|
||||
- **Composer-Sicherheitshinweise**: `composer audit` meldet 34 Hinweise in 8 Paketen (bestanden schon
|
||||
vor der Umstellung) — eigenes Paket.
|
||||
- **Laravel 12**: `composer audit` meldet noch 3 Hinweise zu `laravel/framework` — Fixes gibt es nur in
|
||||
12.x/13.x, Laravel 11 bekommt keine Sicherheitsupdates mehr. Stand 08.10.:
|
||||
- CRLF in der `email`-Regel (hoch): Fix aus 12.60 rückportiert (`App\Support\Validation\Validator`,
|
||||
registriert in `AppServiceProvider`, Test `EmailRuleLineBreakTest`) — nach dem Update entfernen.
|
||||
- Temporäre signierte URLs (mittel): betrifft nur `Storage::temporaryUrl()` auf dem lokalen Disk — im
|
||||
Code nicht genutzt.
|
||||
- XSS auf der Debug-Seite (niedrig): nur mit `APP_DEBUG=true`, auf Live aus.
|
||||
|
||||
Das Update auf Laravel 12 ist ein eigenes Paket.
|
||||
- **PDF-Seitenzahlen** (Befund beim dompdf-Update, schon vorher so): In `pdf/invoice`, `delivery`,
|
||||
`credit` und `cancellation` steht das `page_script` am Anfang des `<body>` und wirkt deshalb nur auf
|
||||
Seite 1 — „Seite x/y“ erscheint auf mehrseitigen Rechnungen nie. In `credit_details*` steht es am
|
||||
Ende und funktioniert. Außerdem fehlt die Übersetzung `pdf.delivery_note_no` (Lieferschein zeigt den
|
||||
Schlüssel).
|
||||
|
||||
### Composer-Sicherheitshinweise (08.10.2026)
|
||||
|
||||
`composer audit`: 34 Hinweise in 8 Paketen → 3 in `laravel/framework` (siehe oben).
|
||||
|
||||
- Patch-/Minor-Updates: `guzzlehttp/guzzle` 7.15, `league/commonmark` 2.10, `league/flysystem` 3.36,
|
||||
`maatwebsite/excel` 3.1.70, `phpoffice/phpspreadsheet` 1.30.7, `phpseclib/phpseclib` 3.0.57,
|
||||
`laravel/framework` (11.x) und Abhängigkeiten.
|
||||
- `barryvdh/laravel-dompdf` 2.2 → 3.1 (dompdf 2.0 → 3.1). Rechnung, Lieferschein und Gutschrift-Details
|
||||
vorher/nachher verglichen: identisch. `enable_remote` ist jetzt standardmäßig aus — die PDF-Vorlagen
|
||||
laden Schriften lokal aus `public/fonts`, Bilder per URL gibt es nicht. Test: `tests/Feature/Pdf`.
|
||||
- Testsuite vorher und nachher: dieselben 88 vorbestehenden Fehlschläge, keine neuen.
|
||||
|
||||
- **Passport-Schlüssel** (`storage/oauth-*.key`) standen bis 08.10. in der Git-Historie. Falls sie nicht
|
||||
mit den Zugangsdaten getauscht wurden: `php artisan passport:keys --force` — alle API-Tokens werden ungültig.
|
||||
|
|
|
|||
62
tests/Feature/Pdf/PdfPipelineTest.php
Normal file
62
tests/Feature/Pdf/PdfPipelineTest.php
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
use App\Libraries\InvoicePDF;
|
||||
use App\Libraries\MyPDFMerger;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use setasign\Fpdi\Fpdi;
|
||||
use Tests\TestCase;
|
||||
|
||||
uses(TestCase::class);
|
||||
|
||||
/**
|
||||
* Rechnungen, Lieferscheine und Gutschriften laufen über dompdf mit
|
||||
* eingebettetem PHP (Seitenzahlen per page_script/page_text) und werden
|
||||
* anschließend mit FPDI auf das Briefpapier gelegt. Schützt diesen Weg bei
|
||||
* Updates von dompdf oder FPDI.
|
||||
*
|
||||
* page_script wirkt nur auf Seiten, die beim Aufruf schon gerendert sind —
|
||||
* das Skript muss deshalb am Ende des <body> stehen (wie in credit_details).
|
||||
*/
|
||||
beforeEach(function () {
|
||||
$this->pdfDir = storage_path('framework/testing/pdf-pipeline-'.uniqid()).'/';
|
||||
File::ensureDirectoryExists($this->pdfDir);
|
||||
View::addLocation($this->pdfDir);
|
||||
|
||||
File::put($this->pdfDir.'pdf-probe.blade.php', <<<'BLADE'
|
||||
<html><body>
|
||||
<p>Seite eins</p>
|
||||
<div style="page-break-before: always;">Seite zwei</div>
|
||||
<script type="text/php">
|
||||
if (isset($pdf)) {
|
||||
$pdf->page_script('$GLOBALS["pdfProbePages"][] = $PAGE_NUM."/".$PAGE_COUNT;');
|
||||
}
|
||||
</script>
|
||||
</body></html>
|
||||
BLADE);
|
||||
|
||||
$GLOBALS['pdfProbePages'] = [];
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
File::deleteDirectory($this->pdfDir);
|
||||
unset($GLOBALS['pdfProbePages']);
|
||||
});
|
||||
|
||||
test('embedded php runs on every page of an invoice pdf', function () {
|
||||
$file = (new InvoicePDF('pdf-probe'))->create([], 'probe.pdf', 'save', $this->pdfDir);
|
||||
|
||||
expect($file)->toBe($this->pdfDir.'probe.pdf')
|
||||
->and(file_get_contents($file))->toStartWith('%PDF')
|
||||
->and($GLOBALS['pdfProbePages'])->toBe(['1/2', '2/2']);
|
||||
});
|
||||
|
||||
test('the rendered pdf can be laid onto the letterhead template', function () {
|
||||
$file = (new InvoicePDF('pdf-probe'))->create([], 'probe.pdf', 'save', $this->pdfDir);
|
||||
|
||||
$merged = (new MyPDFMerger)->addPDF($file)->myMerge('string', 'probe.pdf', 'template_invoice_de');
|
||||
File::put($this->pdfDir.'merged.pdf', $merged);
|
||||
|
||||
expect($merged)->toStartWith('%PDF')
|
||||
->and((new Fpdi)->setSourceFile($this->pdfDir.'merged.pdf'))->toBe(2);
|
||||
});
|
||||
33
tests/Feature/Validation/EmailRuleLineBreakTest.php
Normal file
33
tests/Feature/Validation/EmailRuleLineBreakTest.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use App\Support\Validation\Validator as SafeEmailValidator;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Tests\TestCase;
|
||||
|
||||
uses(TestCase::class);
|
||||
|
||||
/**
|
||||
* Rückportierter Fix aus Laravel 12.60 (GHSA-5vg9-5847-vvmq): Adressen mit
|
||||
* Zeilenumbruch sind nach RFC teils gültig, ermöglichen aber das Einschleusen
|
||||
* von Mail-Headern. Die email-Regel muss sie in jeder Variante ablehnen.
|
||||
*/
|
||||
test('the application uses the validator with the line break check', function () {
|
||||
expect(Validator::make([], []))->toBeInstanceOf(SafeEmailValidator::class);
|
||||
});
|
||||
|
||||
test('addresses with line breaks are rejected', function (string $email, string $rule) {
|
||||
expect(Validator::make(['email' => $email], ['email' => $rule])->fails())->toBeTrue();
|
||||
})->with([
|
||||
'quoted local part' => "\"a\r\n b\"@example.com",
|
||||
'folded local part' => "a\r\n @example.com",
|
||||
'comment' => "(c\r\n )a@example.com",
|
||||
'bare line feed' => "\"a\n b\"@example.com",
|
||||
])->with(['email', 'email:rfc', 'required|email|max:191']);
|
||||
|
||||
test('ordinary addresses stay valid', function (string $email) {
|
||||
expect(Validator::make(['email' => $email], ['email' => 'email'])->passes())->toBeTrue();
|
||||
})->with([
|
||||
'kunde@example.com',
|
||||
'vor.name+shop@sub.example.de',
|
||||
'müller@example.de',
|
||||
]);
|
||||
Loading…
Add table
Add a link
Reference in a new issue