security.txt in PHP konfigurieren
Schritt-für-Schritt-Anleitung: security.txt in PHP dynamisch generieren — mit automatischem Ablaufdatum, PGP-Signatur und RFC 9116-Konformität.
security.txt in PHP
security.txt (RFC 9116) ist eine standardisierte Datei unter /.well-known/security.txt, die Sicherheitsforschern den Kontakt zu Ihrem Security-Team ermöglicht. Ohne diese Datei wissen Forscher nicht, wohin sie Schwachstellen melden sollen. Mit 4 von 166 Punkten im Wolf-Agents Web Security Check.
In PHP können Sie security.txt als statische Datei ablegen oder per PHP-Script dynamisch generieren. Der Vorteil der dynamischen Variante: Das Ablaufdatum (Expires) wird automatisch berechnet, sodass die Datei nie veraltet. Die Datei muss unter /.well-known/security.txt erreichbar sein — nicht unter dem Root-Pfad.
Anders als Security-Header ist security.txt keine HTTP-Header-Konfiguration, sondern eine Textdatei mit dem Content-Type text/plain. Sie brauchen ein PHP-Script, das den korrekten Content-Type setzt, oder eine statische .txt-Datei. Optional können Sie die Datei PGP-signieren für zusätzliche Authentizität.
security.txt in PHP erstellen
Drei Varianten: Ein PHP-Script mit dynamischem Expires, eine .htaccess-Rewrite-Regel für den korrekten Pfad, und eine Framework-Controller-Variante für Laravel/Symfony. Die dynamische Methode ist empfohlen, weil das Ablaufdatum automatisch aktuell bleibt.
<?php
// .well-known/security.txt.php — RFC 9116
header('Content-Type: text/plain; charset=utf-8');
$expires = date('Y-m-d\TH:i:sP', strtotime('+1 year'));
echo "Contact: mailto:security@ihre-domain.de\n";
echo "Expires: {$expires}\n";
echo "Preferred-Languages: de, en\n";
echo "Canonical: https://ihre-domain.de/.well-known/security.txt\n";
echo "Policy: https://ihre-domain.de/security-policy\n";
echo "Encryption: https://ihre-domain.de/.well-known/pgp-key.txt\n"; # .htaccess — Rewrite fuer security.txt
# Leitet /.well-known/security.txt auf PHP-Script um
RewriteEngine On
RewriteRule ^.well-known/security\.txt$ .well-known/security.txt.php [L]
# Alternative: Statische Datei direkt ablegen unter
# .well-known/security.txt (kein PHP noetig)
# Nachteil: Expires muss manuell aktualisiert werden <?php
// src/Controller/SecurityTxtController.php
// Fuer Laravel, Symfony oder Slim
namespace App\Controller;
class SecurityTxtController
{
public function __invoke(): Response
{
$expires = date('Y-m-d\TH:i:sP',
strtotime('+1 year'));
$content = implode("\n", [
"Contact: mailto:security@ihre-domain.de",
"Expires: {$expires}",
"Preferred-Languages: de, en",
"Canonical: https://ihre-domain.de/.well-known/security.txt",
"Policy: https://ihre-domain.de/security-policy",
]);
return new Response($content, 200, [
'Content-Type' => 'text/plain; charset=utf-8',
]);
}
} Seit RFC 9116 sind Contact und Expires Pflichtfelder. Preferred-Languages, Canonical, Policy und Encryption sind optional, aber empfohlen. Wolf-Agents prüft alle Felder und bewertet die Vollständigkeit.
Konfiguration verifizieren
Prüfen Sie die security.txt unter dem korrekten Pfad /.well-known/security.txt. Der Content-Type muss text/plain sein, und das Expires-Datum darf nicht in der Vergangenheit liegen.
# security.txt pruefen
curl -s https://ihre-domain.de/.well-known/security.txt
# Erwartete Ausgabe:
Contact: mailto:security@ihre-domain.de
Expires: 2027-03-28T00:00:00+00:00
Preferred-Languages: de, en
Canonical: https://ihre-domain.de/.well-known/security.txt
# Content-Type pruefen:
curl -sI https://ihre-domain.de/.well-known/security.txt | grep content-type
# Muss text/plain sein Häufige Fehler
Expires abgelaufen
Das Expires-Feld ist Pflicht in RFC 9116. Ein abgelaufenes Datum signalisiert, dass die Datei nicht gepflegt wird. Die dynamische PHP-Variante berechnet das Datum automatisch — kein manuelles Update nötig. Wolf-Agents wertet abgelaufene security.txt als Fehler.
Falscher Pfad
Die Datei muss unter /.well-known/security.txt erreichbar sein, nicht unter /security.txt. Prüfen Sie die Rewrite-Regel in .htaccess oder die Nginx-Konfiguration. Viele Hoster blockieren den .well-known-Ordner — testen Sie den Zugriff.
Content-Type fehlt oder falsch
Die Datei muss mit Content-Type: text/plain ausgeliefert werden. Ohne expliziten header()-Aufruf setzt PHP text/html, was RFC 9116 widerspricht. Setzen Sie den Content-Type immer explizit in der ersten Zeile des Scripts.
PGP-Signatur ungültig
Wenn Sie die Datei PGP-signieren (empfohlen), muss die Signatur den gesamten Inhalt umschließen. Änderungen am Inhalt invalidieren die Signatur — generieren Sie nach jeder Änderung eine neue. Bei der dynamischen PHP-Variante ändert sich der Expires-Wert täglich.
Compliance-Relevanz
Wie steht Ihre Domain bei security.txt?
Prüfen Sie es jetzt — kostenlos, ohne Registrierung, mit 166 Prüfpunkte.