Harden KantSites after the security review

- The installer only opens with a per-installation key that install.php
  creates and shows; the key is deleted with the first account.
- Lock files keep .env, the database, backups and logs out of reach when a
  domain points at the project folder instead of public/.
- Linked sections render by their own schema version, so an old section
  cannot carry unfiltered HTML into a newer page.
- Editors no longer move, trash or change areas and post data of published
  pages; a scheduled publication goes live with the revision that was
  scheduled (migration 20261012000100).
- Form stamps are bound to their form, IPv6 senders count per /64, and a
  flood per form or overall stops storing with a visible message.
- The consent redirect rejects control characters, update targets must look
  like 1.2.3, and own CSS cannot reach outside its block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5.5 committed 2026-10-12 14:38:25 +02:00
1 parent 14e7a3b310
commit ad7c333215
43 files changed
+810 -53

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
{% extends 'install/base.html.twig' %}
{% block heading %}Installationsschlüssel{% endblock %}
{% block lead %}
<p class="muted">Damit niemand anderes diese Installation zu Ende führt, öffnet sich der Installer nur mit dem Schlüssel dieser Installation. Er steht auf der Abschlussseite von <code>install.php</code>. Wer die Dateien per FTP hochgeladen hat, findet ihn in der Datei <code>{{ keyFile }}</code> – herunterladen und öffnen, er besteht aus 32 Zeichen.</p>
{% endblock %}
{% block content %}
<form method="post" action="{{ path('install_key') }}">
<label for="schluessel">Schlüssel</label>
<input id="schluessel" name="schluessel" required maxlength="80" autocomplete="off" spellcheck="false" autofocus>
<p class="muted">Mit dem ersten Konto ist die Installation abgeschlossen; dann wird der Schlüssel gelöscht.</p>
<div class="sheet-actions">
<button class="primary" type="submit">Weiter <span aria-hidden="true">→</span></button>
</div>
</form>
{% endblock %}