Search by

teufels / tt3-wellknown

teufels

[teufels] well-known - Serve the well-known resources a TYPO3 site should provide, maintained in the site configuration

Package info

bitbucket.org/teufels/tt3-wellknown

Homepage

Issues

Type:typo3-cms-extension

pkg:composer/teufels/tt3-wellknown

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

1.0.0 2026-10-16 09:45 UTC

This package is auto-updated.

Last update: 2026-10-16 09:57:53 UTC


README

VENDOR PACKAGE KEY version

[ ṯeufels ] Well-Known

Serve the /.well-known/ resources a TYPO3 site should provide, maintained in the site configuration

Supported resources:

This version supports TYPO3

TYPO3Version TYPO3Version

Composer support

composer req teufels/tt3-wellknown

Quick Start

Minimum to do after installation:

  1. composer req teufels/tt3-wellknown
  2. vendor/bin/typo3 upgrade:run tt3Wellknown_securityTxtDefault (writes the default text into every site)
  3. Backend: Site Management > Sites > your site > tab Well-Known
  4. Maintain Contact: remove the # and enter a real contact, e.g. Contact: mailto:security@your-domain.com
  5. Save and check https://your-domain.com/.well-known/security.txt

As long as Contact is commented out (default), the URL answers with 404. This is intended, so a placeholder contact never goes live.

Requirements

  • TYPO3 13.4 / 14.3, PHP 8.2+
  • /.well-known/ must reach TYPO3 (index.php) if no physical file exists (TYPO3 default .htaccess / nginx config allow it)

How to use

Administrator

  • Install with composer
  • Run the upgrade wizard tt3Wellknown_securityTxtDefault (repeatable, can run on every deployment with vendor/bin/typo3 upgrade:run)
    • sets the default text where wellknownSecurityTxt is missing or empty
    • existing values are never overwritten
  • Additionally the Sites module pre-fills the field with the default if a site has no value yet
  • With lochmueller/staticfilecache: verify with curl -sI that the response is not cached

Editor / Integrator

  • Site Management > Sites > site > tab Well-Known > field security.txt
  • Each site (domain) has its own text, stored in config/sites/<site>/config.yaml as wellknownSecurityTxt
  • Default text:
    # Contact: mailto:security@example.com
    Expires: {{expires(11M)}}
    Preferred-Languages: {{languages}}
    Canonical: {{canonical}}
    

Documentation

Behaviour

RequestResult
GET/HEAD /.well-known/security.txt200, text/plain; charset=utf-8, X-Content-Type-Options: nosniff, Cache-Control: public, max-age=3600
GET/HEAD /security.txt301 to /.well-known/security.txt (only if deliverable)
other methods, empty field, text > 8 KB, invalid contentpassed on, normal TYPO3 404

If the site base contains a path (e.g. https://example.com/de/), the site is found via its host.

Validation (invalid = 404 + log warning)

The file is only delivered if, after placeholder replacement:

  • every placeholder is valid and well-formed (unknown, invalid, empty-resulting or unclosed placeholders invalidate the whole file)
  • exactly one non-commented Contact: line with a value exists (field name is case-insensitive)
  • exactly one non-commented Expires: line with an ISO 8601 / RFC 3339 date in the future exists (expired files are never served)

The reason is logged as a warning (PSR-3, with the site identifier), e.g. in var/log/. An empty field is not logged.

Placeholders

PlaceholderResult
{{expires}}start of the current month (00:00 UTC) + 11 months, e.g. 2027-09-01T00:00:00.000Z
{{expires(nX)}}months (M) and years (Y) count from the start of the current month, days (D) from the start of the current day, e.g. {{expires(6M)}}
{{languages}}ISO language codes of the site, default language first, e.g. de, en
{{canonical}}https://<host>[:port]/.well-known/security.txt from the request

Expires more than 12 months ahead is delivered but logged as a warning (RFC 9116 recommends less than one year).

The Expires value is computed on every request but only changes once a month (M/Y) or once a day (D), so the remaining validity of the default {{expires(11M)}} is always between 10 and 11 months and the file never goes stale. Fixed dates (e.g. Expires: 2027-09-15T00:00:00Z) are also supported; they expire for real and result in a 404 after that date.

PGP-signed text

Text starting with -----BEGIN PGP SIGNED MESSAGE----- is delivered unchanged (no placeholders, no normalization), because any change would invalidate the signature. Contact and Expires are still validated.

Status report (System > Reports)

If EXT:reports is installed, System > Reports > Status Report shows one entry per site:

SeverityMeaning
OKsecurity.txt is deliverable, shows the URL and the current Expires
Warningnot delivered (404), with the reason (e.g. no valid Contact, invalid placeholder, expired Expires)
Noticeno text maintained for the site

The report uses the same validation as the delivery, so a green entry means the URL answers with 200.

Extending

Implement Teufels\Tt3Wellknown\Handler\WellKnownHandlerInterface (auto-tagged) to serve further /.well-known/* resources.

Changelog

1.0.x

  • 1.0.0 initial stable release

    0.2.x

  • 0.2.0 status report (System > Reports > Status Report) per site: OK / invalid with reason / not configured (only if EXT:reports is installed)
  • 0.2.0 Expires is snapped to the start of the month (M/Y) or day (D) so it does not change on every request
  • 0.2.0 shared validation for delivery and report (SecurityTxtEvaluator)

    0.1.x: initial (beta)

  • serves /.well-known/security.txt per site (GET/HEAD), redirect /security.txt => /.well-known/security.txt (301)
  • new tab Well-Known in Sites module (wellknownSecurityTxt)
  • placeholders {{expires}}, {{expires(nD|nM|nY)}}, {{languages}}, {{canonical}}
  • strict validation: invalid placeholder, missing/commented Contact, missing/duplicate/expired Expires => 404 + log
  • PGP-signed text delivered unchanged
  • upgrade wizard tt3Wellknown_securityTxtDefault