Search by

mindtwo / base-security-txt

mindtwo

Framework-agnostic core of the mindtwo security.txt packages: validates input and renders an RFC 9116 security.txt whose expiry follows the last confirmation.

Package info

github.com/mindtwo/base-security-txt

pkg:composer/mindtwo/base-security-txt

Statistics

Installs: 31

Dependents: 3

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-11-05 11:49 UTC

This package is auto-updated.

Last update: 2026-11-05 11:54:30 UTC


README

Tests PHPStan Level 8 PHP 8.0+ License: MIT

Framework-agnostic core of the mindtwo security.txt packages. It validates the input and renders a security.txt (RFC 9116) whose Expires follows the last confirmation: whoever maintains the file only has to check and save it once a year, nobody edits a date, and a file nobody confirms expires as the RFC intends.

Used by mindtwo/wordpress-security-txt, mindtwo/craftcms-security-txt and mindtwo/statamic-security-txt. No runtime dependencies.

Usage

use Mindtwo\SecurityTxt\SecurityTxt;
use Mindtwo\SecurityTxt\Settings;
use Mindtwo\SecurityTxt\Validator;

// On save: normalise and validate the form input.
$settings = Settings::fromArray([
    'contact' => "security@example.com\n+49 228 123456",
    'policy' => 'https://example.com/security-policy',
    'preferred_languages' => 'de, en',
]);

$violations = Validator::validate($settings); // list<Violation>, empty when valid
// store $settings->toArray() together with the time of the save

// On request: render the file, or answer 404 when null.
$body = SecurityTxt::fromInput($storedArray, $confirmedAt, ['https://example.com/.well-known/security.txt']);
Contact: mailto:security@example.com
Contact: tel:+49228123456
Expires: 2027-11-04T09:16:54Z
Preferred-Languages: de, en
Canonical: https://example.com/.well-known/security.txt
Policy: https://example.com/security-policy
Class Responsibility
Settings Normalises input: e-mail addresses become mailto:, + numbers become tel:, every value is a single line. toArray() is the storage format shared by all plugins.
Validator RFC 9116 checks: at least one contact, https for every web URI (dns:/openpgp4fpr: allowed for Encryption), valid language tags. Returns Violations with a code for translation and an English message().
Expiry after($confirmedAt) = 364 days later in UTC (the RFC recommends less than a year), status() = valid, expiring (30 days) or expired.
SecurityTxt Renders the body in a stable field order; holds PATH, LEGACY_PATH and CONTENT_TYPE.

Not supported on purpose: OpenPGP signatures (the signing key does not belong on a web server, and any edit would break the signature).

Development

composer install
composer check   # pint --test, phpstan (level 8), pest

License

MIT, see LICENSE.md.