Kopfdaten und Grenzen
- Release
- 7.0.8 → 7.0.9
- Commits
- 25
- Geänderte Dateien
- 248
- Analyse
- 11.08.2026
- Schwerpunkt
- Sicherheit + Stabilisierung
Nicht untersucht
Verglichen wurden die Tags 7.0.8+260806 und 7.0.9+260812; beide sind im Repository vorhanden und wurden über git log --oneline 7.0.8+260806..7.0.9+260812 und git diff --stat 7.0.8+260806..7.0.9+260812 ausgewertet. Nicht untersucht wurden die Inhalte des Verzeichnisses vendor/, das den weit überwiegenden Teil der 248 geänderten Dateien ausmacht und dessen Dateien im Diff durchgängig als Binärdateien geführt werden — Aussagen über das Verhalten der aktualisierten Fremdbibliotheken selbst stützen sich daher ausschließlich auf die Metadaten in composer.lock und nicht auf deren Quelltext. Ebenfalls nicht ausgewertet wurden die Übersetzungsdateien unterhalb von locale/ sowie die Build-Artefakte des React-Editors, weshalb offenbleibt, ob eine Zeichenkettenänderung in einer bestimmten Sprache vollständig nachgezogen ist. Indirekte Effekte über transitive Drittabhängigkeiten sind durch reine Diff-Analyse nicht vollständig erfassbar, insbesondere nicht bei den in diesem Release angehobenen HTTP- und Kryptobibliotheken. Die Kurzliste musste keine Einträge auslassen.
Executive Summary
7.0.9 ist ein reines Wartungsrelease: vier als Sicherheitsfehler gekennzeichnete Korrekturen, eine Datenbankmigration für PostgreSQL-Installationen und eine Reihe kleinerer Korrekturen an Oberfläche, Statistik und RemoteControl. Die schwerwiegendste Änderung schließt einen unauthentifizierten Aufruf beliebiger Methoden eines mitgelieferten Plugins; die praktisch folgenreichste ist die Reparatur der PostgreSQL-Sequenzen, ohne die Umfragen, die vor dem Umstieg auf Version 7 aktiv waren, beim Speichern von Antworten scheitern. Am ehesten unbemerkt bleibt die Umbenennung des Zählerplatzhalters bei der Erzeugung von Dummy-Teilnehmern: Bestehende Eingaben werden nicht mehr ersetzt, sondern wörtlich übernommen, ohne dass eine Fehlermeldung erscheint. Für Theme-Entwickler enthält das Release keine vollständig beschriebene Änderung, wohl aber mehrere Anpassungen am ausgelieferten Markup und an mitgelieferten Twig-Views.
- Willkürlicher Methodenaufruf im Zwei-Faktor-Plugin unterbunden
- Reparatur der PostgreSQL-Sequenzen nach dem Umstieg auf Version 7
- Server-Side-Request-Forgery in der Vorlagen-API geschlossen
- Berechtigungsprüfung beim Abruf der Fragedaten ergänzt
- Berechtigungsprüfung in der Antwortzeiten-Statistik ergänzt
- Zählerplatzhalter für Dummy-Teilnehmer umbenannt
- OpenAPI-Bibliothek auf einen Fork mit Entwicklungszweig umgestellt
- Quartile für verschlüsselte numerische Daten werden nicht mehr berechnet
Upgrade-Empfehlung
✅ Sofort installieren
Das Release schließt einen unauthentifiziert erreichbaren Methodenaufruf sowie zwei fehlende Berechtigungsprüfungen im Administrationsbereich. Die einzige Datenbankmigration verändert ausschließlich Sequenzwerte und keine Tabellenstruktur. Nachzuarbeiten ist lediglich der umbenannte Zählerplatzhalter, sofern gespeicherte Vorgaben für Dummy-Teilnehmer verwendet werden.
Lesepfad
| Zielgruppe | Relevante Kennungen und Kapitel |
|---|---|
| Administratoren | A1, A2, A3, A4, A5, A6, A7, A8, Weitere relevante Änderungen, Empfehlung |
| Plugin-Entwickler | A1, A7, Weitere relevante Änderungen, Empfehlung |
| Theme-Entwickler | keine Kennung, Weitere relevante Änderungen, Empfehlung |
| Integratoren | A1, A2, A3, A4, A6, A8, Weitere relevante Änderungen, Empfehlung |
| API-Nutzer | A3, A7, Weitere relevante Änderungen, Empfehlung |
Die wichtigsten Änderungen
A1: Willkürlicher Methodenaufruf im Zwei-Faktor-Plugin unterbunden
Hintergrund: Das mitgelieferte Plugin TwoFactorAdminLogin reagiert auf das Ereignis newDirectRequest, das über den öffentlichen Endpunkt für direkte Plugin-Aufrufe erreichbar ist. Der zugehörige Handler übernahm den Parameter function unverändert aus der Anfrage und rief die gleichnamige Methode auf, sobald method_exists() sie fand. Damit ließ sich jede öffentliche, geschützte oder private Methode der Plugin-Klasse aus einer angreiferkontrollierten Zeichenkette heraus ausführen, ohne dass eine Anmeldung erforderlich war. Derselbe Aufbau bestand für das nur über die Konsole ausgelöste Ereignis direct. Zusätzlich unterschied der Handler nicht zwischen lesenden und schreibenden Aufrufen, sodass datenverändernde Operationen auch per GET auslösbar waren.
Konsequenz: Der Endpunkt akzeptiert nur noch drei ausdrücklich freigegebene Methodennamen für den Web-Pfad und zwei für den Konsolen-Pfad; jeder andere Wert führt zu einem wirkungslosen Rücksprung. Die beiden datenverändernden Methoden verlangen zusätzlich eine POST-Anfrage und quittieren einen GET-Aufruf mit HTTP 405. Wer eigene Automatisierung gegen diesen Endpunkt gebaut hat und dabei GET verwendet oder einen anderen Methodennamen anspricht, erhält nach dem Update entweder einen Fehler 405 oder eine leere Antwort. Für abgeleitete oder ersetzte Fassungen des Plugins greift die Absicherung nicht: Die Freigabelisten sind private Eigenschaften der mitgelieferten Klasse, und Drittanbieter-Plugins, die dem gleichen Muster folgen, bleiben unverändert offen.
Vorher / Nachher:
// Vorher (application/core/plugins/TwoFactorAdminLogin/TwoFactorAdminLogin.php)
$action = $oEvent->get('function');
if (method_exists($this, $action)) {
call_user_func([$this, $action], $oEvent, $request);
}
// Nachher
$action = $oEvent->get('function');
if (!in_array($action, $this->allowedDirectMethods, true) || !method_exists($this, $action)) {
return;
}
// Data-modifying actions must never run on a safe (GET) request.
if (in_array($action, $this->writeDirectMethods, true) && !$request->getIsPostRequest()) {
throw new CHttpException(405, 'This action requires a POST request.');
}
call_user_func([$this, $action], $oEvent, $request);
// Neu (application/core/plugins/TwoFactorAdminLogin/TwoFactorAdminLogin.php)
private $allowedDirectMethods = [
'directCallCreateNewKey',
'directCallConfirmKey',
'directCallDeleteKey',
];
...
private $writeDirectMethods = [
'directCallConfirmKey',
'directCallDeleteKey',
];
Nach dem Update testen: Zwei-Faktor-Schlüssel im Benutzerprofil anlegen, bestätigen und löschen und prüfen, dass alle drei Vorgänge weiterhin durchlaufen. Anschließend denselben Endpunkt mit einem beliebigen anderen Wert im Parameter function aufrufen und sicherstellen, dass keine Wirkung eintritt, sowie einen Löschaufruf per GET absetzen und die Antwort 405 bestätigen.
Betroffene Dateien: application/core/plugins/TwoFactorAdminLogin/TwoFactorAdminLogin.php
Relevante Commits: b65b5068b3, a2ecc93290
CVE / Advisory: Im Repository findet sich keine CVE-Kennung. Der Commit ist in der Betreffzeile ausdrücklich mit [security] markiert und verweist auf Issue #20642 sowie Pull Request #5219; derselbe Eintrag steht in docs/release_notes.txt.
A2: Reparatur der PostgreSQL-Sequenzen nach dem Umstieg auf Version 7
Hintergrund: Die Migration auf Version 7 baut die Antwort- und Zeitmessungstabellen neu auf und legt dabei eine frische Spalte id vom Typ serial an, deren zugehörige PostgreSQL-Sequenz bei 1 beginnt. Die vorhandenen Datensätze wurden anschließend mit ihren ursprünglichen Werten kopiert, was die Sequenz nicht weiterschaltet. Beim nächsten Antworteingang kollidierte der von der Sequenz gelieferte Wert mit einem bereits vergebenen Primärschlüssel. Für genau diesen Zweck existiert die Hilfsfunktion fixPostgresSequence(), die alle Sequenzen einer Datenbank auf das Maximum der zugehörigen Spalte setzt. Ihre Variante ohne Tabellenname war jedoch unbrauchbar, weil die abschließende Sortierklausel ohne trennendes Leerzeichen an den Tabellennamen der WHERE-Bedingung angehängt wurde.
Konsequenz: Installationen auf PostgreSQL, die vor dem Umstieg auf Version 7 aktive Umfragen hatten, speichern wieder Antworten, ohne dass die Meldung über einen Fehler beim Speichern erscheint. Die Reparatur läuft automatisch als Teil des Datenbank-Updates und erfordert keinen manuellen Eingriff. Für Installationen auf MySQL, MariaDB und SQL Server bleibt die Migration wirkungslos, weil sie sich ausdrücklich auf den Treibernamen pgsql beschränkt. Wer die Migration von Version 6 auf Version 7 erst nach diesem Update ausführt, erhält die Sequenzkorrektur bereits im Verlauf der Version-7-Migration; für bereits migrierte Datenbanken übernimmt sie die neue Migration auf Datenbankstand 710.
Vorher / Nachher:
// Vorher (application/helpers/update/updatedb_helper.php)
$query .= "ORDER BY S.relname;";
// Nachher
$query .= " ORDER BY S.relname;";
// Neu (application/helpers/update/updates/Update_710.php)
class Update_710 extends DatabaseUpdateBase
{
...
public function up()
{
if ($this->db->getDriverName() !== 'pgsql') {
return;
}
\fixPostgresSequence();
}
}
// Neu (application/helpers/update/updates/Update_700.php)
if (Yii::app()->db->getDriverName() === 'pgsql') {
\fixPostgresSequence();
}
Migrationsdetails: Die interne Datenbank-Versionsnummer steigt von 709 auf 710, belegt durch $config['dbversionnumber'] = 709; vor und $config['dbversionnumber'] = 710; nach dem Update in application/config/version.php. Die Migration ändert ausschließlich Werte und keine Struktur: Der einzige ausgeführte Aufruf ist \fixPostgresSequence(), dessen zitierte Implementierung ausschließlich SETVAL-Anweisungen auf COALESCE(MAX(...), 1) erzeugt; sie ist damit idempotent, weil ein wiederholter Lauf denselben Wert setzt. Die Datei enthält ausschließlich eine Methode up(); eine Rücknahme ist im Diff nicht vorgesehen, weshalb die Rückwärtskompatibilität des Datenbankstands 710 gegenüber der Codebasis von 7.0.8 nicht bestimmbar ist.
Nach dem Update testen: Auf einer PostgreSQL-Installation eine vor dem Umstieg auf Version 7 aktive Umfrage aufrufen, eine Antwort vollständig abschicken und prüfen, dass sie in der Antworttabelle erscheint. Zusätzlich in der Datenbank SELECT last_value FROM <sequenz> für die Antworttabelle abfragen und gegen MAX(id) derselben Tabelle abgleichen.
Betroffene Dateien: application/helpers/update/updates/Update_710.php, application/helpers/update/updates/Update_700.php, application/helpers/update/updatedb_helper.php, application/config/version.php
Relevante Commits: ec53b4bb42
A3: Server-Side-Request-Forgery in der Vorlagen-API geschlossen
Hintergrund: Der API-Befehl, der die gerenderte Umfragevorlage ausliefert, holt den Umfrageinhalt über eine serverseitige HTTP-Anfrage an die eigene Installation. Die Basisadresse dieser Anfrage wurde bislang aus $_SERVER['HTTPS'] und $_SERVER['HTTP_HOST'] zusammengesetzt, also aus dem vom Client gesendeten Host-Header. Wer den Header kontrollierte, konnte den Server damit veranlassen, eine Anfrage an einen beliebigen anderen Host zu stellen — einschließlich Adressen im internen Netz, die von außen nicht erreichbar sind. Da die Anfrage das Sitzungscookie der aufrufenden Sitzung mitführt, wurde auch dieses an das fremde Ziel gesendet.
Konsequenz: Die Zieladresse stammt jetzt aus der serverseitig ermittelten Basis-URL der Anwendung. Wie weit das den Angriff ausschließt, hängt vom Betrieb ab: LimeSurvey validiert den ermittelten Hostnamen in application/core/LSHttpRequest.php gegen die Liste erlaubter Hosts, verhält sich dort aber laut der Beschreibung im Quelltext nachsichtig, solange die Datei mit den erlaubten Hosts nicht angelegt ist. In Installationen ohne konfigurierte Hostliste leitet die zugrunde liegende Yii-Implementierung die Basisadresse weiterhin aus $_SERVER['HTTP_HOST'] ab. Vollständig greift die Korrektur daher nur dort, wo die erlaubten Hosts gepflegt sind oder der Webserver den Host-Header bereits auf bekannte Werte einschränkt. Hinter einem Reverse Proxy, der einen abweichenden Host weiterreicht, kann sich zudem die verwendete Basisadresse gegenüber 7.0.8 ändern und die interne Anfrage ins Leere laufen, was der Befehl als „Survey not found" quittiert.
Vorher / Nachher:
// Vorher (application/libraries/Api/Command/V1/SurveyTemplate.php)
$root = (
!empty($_SERVER['HTTPS'])
? 'https'
: 'http'
) . '://' . ($_SERVER['HTTP_HOST'] ?? '');
// Nachher
// Use the trusted, server-side base URL instead of the client-supplied
// Host header to prevent server-side request forgery (SSRF).
$root = App()->getBaseUrl(true);
Nach dem Update testen: Den Vorlagen-Endpunkt der REST-Schnittstelle für eine aktive Umfrage aufrufen und prüfen, dass die gerenderte Vorlage zurückkommt. Anschließend denselben Aufruf mit einem manipulierten Host-Header wiederholen und bestätigen, dass keine Anfrage an den fremden Host ausgeht — bei aktiver Reverse-Proxy-Konfiguration zusätzlich prüfen, dass die intern verwendete Basisadresse auf die Installation zeigt.
Betroffene Dateien: application/libraries/Api/Command/V1/SurveyTemplate.php
Relevante Commits: 5142dbf253
CVE / Advisory: Eine CVE-Kennung ist im Repository nicht auffindbar. Der Commit trägt die Markierung [security] und bezieht sich auf Issue #20523; der Eintrag ist in docs/release_notes.txt wiederholt.
A4: Berechtigungsprüfung beim Abruf der Fragedaten ergänzt
Hintergrund: Die Aktion actionGetQuestionData des Fragen-Controllers liefert die vollständigen Daten einer Frage samt Umfrageinformationen als JSON an den Frageneditor. Sie ermittelte das Fragenobjekt bislang allein aus der übergebenen Kennung und gab die zusammengestellten Daten unmittelbar zurück, ohne zu prüfen, ob die aufrufende Sitzung überhaupt Leserechte auf den Inhalt der zugehörigen Umfrage besitzt. Jeder angemeldete Benutzer konnte damit die Fragedaten fremder Umfragen abrufen, indem er eine beliebige Fragen-Kennung durchprobierte.
Konsequenz: Der Endpunkt verlangt nun das Recht surveycontent mit der Stufe read auf der Umfrage, zu der die Frage gehört, und beantwortet einen Aufruf ohne dieses Recht mit HTTP 403. Rollen, die den Frageneditor bisher nur über Umwege oder mit unvollständigen Rechten benutzt haben, sehen an dieser Stelle einen Fehler statt der bisherigen Ausgabe. Da die Prüfung nach dem Aufbau des Fragenobjekts erfolgt, wirkt sie auf bestehende Aufrufe erst zum Antwortzeitpunkt und nicht bereits beim Routing. Eigene Werkzeuge, die diesen Endpunkt zum Auslesen von Fragedefinitionen verwenden, müssen mit einem Benutzerkonto arbeiten, das das genannte Recht auf der jeweiligen Umfrage besitzt.
Vorher / Nachher:
// Neu (application/controllers/QuestionAdministrationController.php)
if (!Permission::model()->hasSurveyPermission($oQuestion->sid, 'surveycontent', 'read')) {
throw new CHttpException(403, gT("No permission"));
}
Nach dem Update testen: Mit einem Konto ohne Leserecht auf den Umfrageinhalt die Fragedaten einer fremden Umfrage abrufen und den Statuscode 403 bestätigen. Anschließend mit einem berechtigten Konto denselben Aufruf durchführen und prüfen, dass der Frageneditor die Frage vollständig lädt.
Betroffene Dateien: application/controllers/QuestionAdministrationController.php
Relevante Commits: 52170b96b0
CVE / Advisory: Eine CVE-Kennung findet sich nicht. Der Commit ist mit [security] markiert und nennt Issue #20641 sowie Pull Request #5220.
A5: Berechtigungsprüfung in der Antwortzeiten-Statistik ergänzt
Hintergrund: Die Aktion actionTime des Antworten-Controllers zeigt die Zeitmessungen zu den Antworten einer Umfrage an. Sie lud die Daten bislang unmittelbar über getData(), ohne zu prüfen, ob die aufrufende Sitzung Leserechte auf die Antworten der Umfrage besitzt. Anders als die übrigen Aktionen desselben Controllers fehlte hier die Absicherung vollständig, sodass Zeitmessungsdaten fremder Umfragen über die bloße Kenntnis der Umfrage-Kennung erreichbar waren.
Konsequenz: Die Ansicht verlangt nun das Recht responses mit der Stufe read. Fehlt es, wird eine Fehlermeldung als Flash-Nachricht gesetzt und auf die Umfrageübersicht umgeleitet; die Ausführung endet danach unmittelbar. Benutzer mit eingeschränkten Rechten, die die Zeitmessungen bislang aufrufen konnten, landen nach dem Update auf der Umfrageübersicht. Da die Umleitung auf surveyAdministration/view zeigt, benötigen die betroffenen Konten weiterhin Zugriff auf diese Ansicht, um die Meldung überhaupt zu sehen.
Vorher / Nachher:
// Neu (application/controllers/ResponsesController.php)
if (!Permission::model()->hasSurveyPermission($surveyId, 'responses', 'read')) {
App()->user->setFlash('error', gT("You do not have permission to access this page."));
$this->redirect(['surveyAdministration/view', 'surveyid' => $surveyId]);
App()->end();
}
Nach dem Update testen: Mit einem Konto ohne Leserecht auf Antworten die Zeitmessungsansicht einer Umfrage aufrufen und die Umleitung samt Fehlermeldung bestätigen. Danach mit einem berechtigten Konto dieselbe Ansicht öffnen und prüfen, dass die Zeitspalten wie zuvor angezeigt werden.
Betroffene Dateien: application/controllers/ResponsesController.php
Relevante Commits: 726b102b0e
CVE / Advisory: Eine CVE-Kennung ist nicht auffindbar. Der Commit trägt die Markierung [security] und verweist auf Issue #20644.
A6: Zählerplatzhalter für Dummy-Teilnehmer umbenannt
Hintergrund: Beim Anlegen von Dummy-Teilnehmern ersetzt LimeSurvey in Vorname, Nachname und E-Mail-Adresse einen Platzhalter durch die laufende Nummer des erzeugten Datensatzes. Dieser Platzhalter hieß bisher {TOKEN_COUNTER} und wurde in den drei Feldern per Zeichenkettenersetzung aufgelöst. Mit diesem Release wurde er auf {COUNTER} verkürzt; die Ersetzung im Controller und die Hilfetexte im Formular wurden gemeinsam angepasst. Eine Übergangsbehandlung für den alten Namen ist im Diff nicht erkennbar.
Konsequenz: Wer weiterhin {TOKEN_COUNTER} einträgt — etwa aus einer Arbeitsanweisung, einer gespeicherten Formularvorbelegung oder einem Skript, das das Formular ausfüllt —, erhält Teilnehmerdatensätze, in denen die Zeichenkette wörtlich im Namensfeld steht. Bei der E-Mail-Adresse führt das zu Adressen, die den Platzhalter im lokalen Teil enthalten und damit unzustellbar sind. Es erscheint keine Fehlermeldung, und die Datensätze werden regulär gespeichert; der Fehler fällt erst beim Sichten der erzeugten Teilnehmer oder beim Versand auf. Wer den Dialog manuell bedient, sieht den neuen Namen unmittelbar im Hilfetext unter den drei Feldern.
Vorher / Nachher:
// Vorher (application/controllers/admin/Tokens.php)
$token->firstname = str_replace('{TOKEN_COUNTER}', $newDummyToken, (string) $token->firstname);
$token->lastname = str_replace('{TOKEN_COUNTER}', $newDummyToken, (string) $token->lastname);
$token->email = str_replace('{TOKEN_COUNTER}', $newDummyToken, (string) $token->email);
// Nachher
$token->firstname = str_replace('{COUNTER}', $newDummyToken, (string) $token->firstname);
$token->lastname = str_replace('{COUNTER}', $newDummyToken, (string) $token->lastname);
$token->email = str_replace('{COUNTER}', $newDummyToken, (string) $token->email);
// Vorher (application/views/admin/token/dummytokenform.php)
<?= sprintf(gT('You can use %1$s to add the generated counter number, for example, “Firstname %1$s”.'), "{TOKEN_COUNTER}"); ?>
// Nachher
<?= gT('You can use {COUNTER} to add a generated counter number, for example, “Firstname {COUNTER}”.'); ?>
Neuer Bezugswert: Die laufende Nummer wird künftig über den Platzhalter {COUNTER} in Vorname, Nachname und E-Mail-Adresse eingesetzt. Ob der alte Name irgendwo als Alias weiterlebt, ist im Diff nicht erkennbar; die zitierte Ersetzung kennt ihn nicht mehr.
Nach dem Update testen: Im Dialog für Dummy-Teilnehmer einen Vornamen mit {COUNTER} und eine E-Mail-Adresse nach dem Muster user{COUNTER}@example.org (Beispielwerte) eintragen, mehrere Datensätze erzeugen und in der Teilnehmerliste prüfen, dass die Nummern eingesetzt sind. Zusätzlich einen Durchlauf mit {TOKEN_COUNTER} durchführen und bestätigen, dass die Zeichenkette wörtlich übernommen wird, um bestehende Arbeitsanweisungen zu identifizieren.
Betroffene Dateien: application/controllers/admin/Tokens.php, application/views/admin/token/dummytokenform.php
Relevante Commits: b13918346e, b8708ce517
A7: OpenAPI-Bibliothek auf einen Fork mit Entwicklungszweig umgestellt
Hintergrund: Unter PHP 8.4 meldete LimeSurvey mehrere Verwerfungswarnungen, die aus dem impliziten Markieren von Parametern als nullbar in Fremdbibliotheken stammen. Für die Bibliothek, die die OpenAPI-Beschreibung der REST-Schnittstelle aufbaut, existiert dafür kein veröffentlichtes stabiles Release. Die Abhängigkeit wurde deshalb von einer Versionsbereichs-Angabe auf einen benannten Entwicklungszweig eines fremden Forks umgestellt, und composer.json erhielt dafür einen zusätzlichen VCS-Repositoryeintrag. Im selben Commit wurden weitere Abhängigkeiten angehoben, darunter der HTTP-Client und die Kryptobibliothek.
Konsequenz: Wer die Installation aus dem Paketverzeichnis der Distribution verwendet, merkt hiervon nichts, da vendor/ mit ausgeliefert wird. Wer selbst aus den Paketquellen baut, benötigt beim Auflösen der Abhängigkeiten Zugriff auf github.com und einen funktionierenden Git-Client, weil ein VCS-Repository geklont statt ein Archiv geladen wird; fehlt beides, bricht die Installation ab, bevor die Anwendung startet. composer.lock fixiert den Zweig auf einen konkreten Commit und setzt eine Stabilitätsmarkierung für das Paket, sodass ein Lauf gegen die Sperrdatei reproduzierbar bleibt. Eine Aktualisierung ohne Sperrdatei folgt dagegen dem beweglichen Zweig eines Repositorys, das nicht unter der Kontrolle des LimeSurvey-Projekts steht — eine Abwägung, die vor allem in Umgebungen mit Anforderungen an die Lieferkette geprüft werden sollte.
Vorher / Nachher:
composer.json, vorher:
"goldspecdigital/oooas": "^2.10",
composer.json, nachher:
"goldspecdigital/oooas": "dev-fix-implicitely-marking-parameter-as-nullable-deprecations",
composer.json, neu:
"repositories": {
"oooas": {
"type": "vcs",
"url": "https://github.com/PrinsFrank/goldspecdigital-oooas"
}
}
composer.lock, neu:
"stability-flags": {
"goldspecdigital/oooas": 20,
"tiamo/spss": 20
},
composer.lock, vorher:
"name": "guzzlehttp/guzzle",
"version": "7.11.1",
...
"name": "phpseclib/phpseclib",
"version": "3.0.53",
composer.lock, nachher:
"name": "guzzlehttp/guzzle",
"version": "7.15.3",
...
"name": "phpseclib/phpseclib",
"version": "3.0.56",
Konfiguration: Die Änderung verändert composer.json im Wurzelverzeichnis der Installation. Der oben zitierte Block repositories mit dem Eintrag oooas vom Typ vcs muss vorhanden sein, damit sich die Abhängigkeit überhaupt auflösen lässt; fehlt er — etwa weil eine lokal gepatchte composer.json weiterverwendet wird —, scheitert composer install mit einem nicht auflösbaren Paket. Die im selben Commit angehobenen weiteren Pakete sind in composer.lock festgeschrieben, darunter der HTTP-Client guzzlehttp/guzzle von 7.11.1 auf 7.15.3 und die Kryptobibliothek phpseclib/phpseclib von 3.0.53 auf 3.0.56.
Nach dem Update testen: In einer aus den Paketquellen gebauten Installation composer install gegen die mitgelieferte Sperrdatei ausführen und prüfen, dass das Paket aus dem VCS-Repository aufgelöst wird. Danach die OpenAPI-Beschreibung der REST-Schnittstelle abrufen und unter PHP 8.4 das Fehlerprotokoll auf Verwerfungswarnungen aus dem Paketverzeichnis durchsehen.
Betroffene Dateien: composer.json, composer.lock, application/libraries/Api/Rest/V1/SchemaFactory
Relevante Commits: ae4a42f917
A8: Quartile für verschlüsselte numerische Daten werden nicht mehr berechnet
Hintergrund: Die Quartilberechnung der Statistik sortiert die Antwortwerte in der Datenbank und greift dann auf die Positionen der Grenzwerte zu. Bei einem als verschlüsselt gekennzeichneten Feld liegen in der Datenbank jedoch Geheimtexte, deren Sortierreihenfolge nichts mit der Größe der zugrunde liegenden Zahlen zu tun hat. Die ausgewiesenen Werte für das erste Quartil, den Median und das dritte Quartil waren damit beliebig, wurden aber ohne Kennzeichnung als reguläre Statistikwerte ausgegeben.
Konsequenz: Für verschlüsselte numerische Felder entfällt die Berechnung; die Statistik gibt stattdessen eine einzelne Zeile mit dem Hinweis aus, dass die Kennzahlen für verschlüsselte Daten nicht verfügbar sind. Wer Statistikausgaben maschinell weiterverarbeitet, erhält für diese Felder nicht mehr drei Zeilen mit numerischen Werten, sondern eine Zeile mit einem Text — Auswertungen, die auf feste Zeilenpositionen oder auf numerische Werte an dieser Stelle bauen, müssen angepasst werden. Für unverschlüsselte Felder bleibt Anzahl und Inhalt der Zeilen unverändert. Zahlen, die aus früheren Auswertungen verschlüsselter Felder übernommen wurden, sind rückwirkend als unbrauchbar zu betrachten.
Vorher / Nachher:
// Vorher (application/helpers/admin/statistics_helper.php)
$quartiles[1] = $this->getQuartile(1, $fielddata, $sql, $excludezeros);
$quartiles[2] = $this->getQuartile(2, $fielddata, $sql, $excludezeros);
$quartiles[3] = $this->getQuartile(3, $fielddata, $sql, $excludezeros);
// Nachher
// Encrypted data is sorted by ciphertext, so the ordering does not match the
// numeric values and quartiles cannot be computed reliably (see bug #20569).
$quartilesEncrypted = ($fielddata['encrypted'] === "Y");
if (!$quartilesEncrypted) {
$quartiles[1] = $this->getQuartile(1, $fielddata, $sql, $excludezeros);
$quartiles[2] = $this->getQuartile(2, $fielddata, $sql, $excludezeros);
$quartiles[3] = $this->getQuartile(3, $fielddata, $sql, $excludezeros);
}
// Neu (application/helpers/admin/statistics_helper.php)
if ($quartilesEncrypted) {
$showem[] = array(gT("Quartiles (Q1, Median, Q3)"), gT("Not available for encrypted data"));
} else {
...
}
Neuer Bezugswert: Für verschlüsselte numerische Felder liefert die Statistik keine Quartile mehr. Woher ein Integrator diese Kennzahlen künftig beziehen soll, ist im Diff nicht ersichtlich und bleibt offen; die verbleibenden Kennzahlen wie Anzahl, Minimum und Maximum werden weiterhin ausgegeben.
Nach dem Update testen: Eine numerische Frage mit aktivierter Verschlüsselung mit mehreren Antworten befüllen, die Statistik dieser Frage aufrufen und prüfen, dass an Stelle der drei Quartilzeilen die Hinweiszeile erscheint. Danach dieselbe Auswertung für eine unverschlüsselte numerische Frage öffnen und die drei Quartilzeilen mit plausiblen Werten bestätigen.
Betroffene Dateien: application/helpers/admin/statistics_helper.php
Relevante Commits: 9cc8dcb06f
Weitere relevante Änderungen
Endbildschirm-URLs öffnen in neuem Tab
Survey Runtime · Kein Bruch · Theme-Entwickler, Integratoren
Die Weiterleitungs-Schaltfläche am Ende einer Umfrage öffnet das Ziel künftig in einem neuen Tab mit rel="noopener noreferrer". (58de6826b7)
Standardwert in get_question_properties korrigiert
RemoteControl API · Kein Bruch · API-Nutzer, Integratoren
Der Aufruf ohne optionale Parameter liefert nun den sprachabhängigen Standardwert der Frage zurück, statt mit einem Laufzeitfehler abzubrechen. (de44c68403)
Checkicon-Ausgabe im Fruity-TwentyThree-Header abgesichert
Themes und Rendering · Kein Bruch · Theme-Entwickler, Administratoren
Ohne gesetztes Häkchensymbol erzeugt die Kopfzeile keine ungültige CSS-Regel mehr, sodass die nachfolgenden Regeln wieder greifen. (96e63a4c15)
Platzhalterlisten der E-Mail-Vorlagen wieder gefüllt
Themes und Rendering · Kein Bruch · Administratoren, Integratoren
Die Feldtyp-Kennungen wurden auf Bindestrich-Schreibweise umgestellt, sodass der Vorlageneditor die zugehörigen Platzhalter wieder anbietet. (c026a848e6)
Platzhalterdialog arbeitet mit mehreren Editoren
Themes und Rendering · Kein Bruch · Theme-Entwickler, Integratoren
Der CKEditor-Dialog sucht die Auswahlliste jetzt im eigenen Dialog statt global über die Kennung #cquestions. (ad67d258fa)
Fehlgeschlagene E-Mails im Demo-Modus nicht mehr protokolliert
Survey Runtime · Kein Bruch · Administratoren
Im Demo-Modus werden Benachrichtigungen nicht mehr als fehlgeschlagen gespeichert, wodurch die Fehlermeldung am Umfrageende entfällt. (7f7ff63715)
Obsolete Fortschrittsbalken-Bibliothek entfernt
Plugin-Kompatibilität · Fehler zur Laufzeit · Plugin-Entwickler
Fremdcode, der application.libraries.admin.progressbar importiert oder die Klasse verwendet, findet sie nach dem Update nicht mehr. (d28097e871)
Meldung zur Editor-Inkompatibilität hervorgehoben
Themes und Rendering · Kein Bruch · Theme-Entwickler, Administratoren
Der Hinweis zur Themenkompatibilität des neuen Editors erscheint als Fehlermeldung, und die Anzeigedauer aller Meldungen steigt um eine Sekunde. (016997be62)
Versionskennung des mitgelieferten Dateibrowsers angehoben
Themes und Rendering · Kein Bruch · Administratoren
Die gemeldete Version des Dateibrowsers weist ihn nun als selbst gepflegten Fork aus, damit versionsbasierte Schwachstellen-Scanner nicht mehr die unwartete Vorlage treffen. (4669273167)
Datumsfilter im Benutzerraster auf Feldhöhe angeglichen
Themes und Rendering · Kein Bruch · Theme-Entwickler
Die Filterfelder erhalten feste Inline-Stile für Schriftgröße und Höhe, die eigene CSS-Regeln für diese Spalte überstimmen. (e79e9448bb)
Beschriftungen der Paginierung umbenannt
Themes und Rendering · Kein Bruch · Theme-Entwickler, Integratoren
Die Paginierung des Editors spricht jetzt von Datensätzen statt von Ergebnissen, was auf Text gestützte Übersetzungen und Oberflächentests brechen kann. (b25cd7ffaf)
Zuordnung nach Bereich
| Bereich | Vollständig beschrieben | Weitere Einträge |
|---|---|---|
| Sicherheit | A1, A3, A4, A5 | – |
| Datenbank | A2 | – |
| RemoteControl API | keine | ja |
| Survey Runtime | A6, A8 | ja |
| Themes und Rendering | keine | ja |
| Plugin-Kompatibilität | A1, A7 | ja |
| Performance | keine | – |
Nicht betroffene Bereiche
Die folgenden Beobachtungen stützen sich darauf, dass die genannten Dateien und Mechanismen im Diff zwischen den beiden Tags nicht auftauchen; sie sind keine Garantie.
Die Datei application/config/config-defaults.php erscheint nicht im Diff, weshalb sich an den ausgelieferten Vorgabewerten der Konfiguration nichts erkennen lässt. Der Ereignisverteiler unterhalb von application/libraries/PluginManager/ erscheint nicht im Diff, sodass sich an den Signaturen und Parametern der Plugin-Ereignisse keine Änderung ablesen lässt. Die Auswertung der Ausdruckssprache unterhalb von application/helpers/expressions/ erscheint nicht im Diff. Die Twig-Views unterhalb von themes/survey/vanilla/ erscheinen nicht im Diff, ebenso wenig die Frageansichten unterhalb von application/views/survey/.
Zu Struktur-, Spalten-, Index- und Constraint-Änderungen: Die einzige neue Migration ist Update_710.php, deren vollständiger Rumpf in A2 zitiert ist und ausschließlich aus einer Treiberabfrage und dem Aufruf \fixPostgresSequence() besteht; die zitierte Implementierung dieser Funktion erzeugt ausschließlich SETVAL-Anweisungen. Der interne Datenbankstand steigt dabei von 709 auf 710, wie im Zitat aus application/config/version.php in A2 belegt.
Empfehlung
Administratoren
Vor dem Update: Datenbank und Dateisystem sichern, insbesondere auf PostgreSQL-Installationen, da die Migration (A2) Sequenzwerte in der gesamten Datenbank verändert. Prüfen, ob Arbeitsanweisungen, Vorlagen oder Skripte den bisherigen Zählerplatzhalter für Dummy-Teilnehmer verwenden (A6); diese Stellen vorab notieren. Wer aus den Paketquellen baut, sicherstellen, dass die Bauumgebung Git und Zugriff auf github.com besitzt (A7). Wer eigene Automatisierung gegen den direkten Plugin-Endpunkt betreibt, die verwendeten Methodennamen und HTTP-Verben erfassen (A1).
Unmittelbar nach dem Update: Auf PostgreSQL eine Antwort in einer zuvor aktiven Umfrage abschicken und den Sequenzstand gegen MAX(id) abgleichen (A2). Die Rechteprüfungen mit einem eingeschränkten Konto gegenprüfen, damit produktive Rollen nicht unbeabsichtigt ausgesperrt sind (A4, A5). Die Vorgaben für Dummy-Teilnehmer auf den neuen Platzhalter umstellen (A6). Statistikberichte, die verschlüsselte numerische Felder enthalten, auf die geänderte Ausgabe prüfen (A8). Hinter einem Reverse Proxy zusätzlich den Vorlagen-Endpunkt der REST-Schnittstelle aufrufen und die verwendete Basisadresse kontrollieren (A3).
Rollback: Ein Rückschritt auf 7.0.8 erfordert das Einspielen der vor dem Update angefertigten Sicherung. Der Datenbankstand wird von 709 auf 710 angehoben; die Migration enthält ausschließlich eine up()-Methode, eine Rücknahme ist im Diff nicht vorgesehen. Ob die Codebasis von 7.0.8 mit dem Datenbankstand 710 arbeitet, ist nicht bestimmbar und in einer Testumgebung zu prüfen. Die von der Migration angehobenen Sequenzwerte werden durch ein Zurücksetzen des Codes nicht rückgängig gemacht; ihr Einfluss auf die ältere Codebasis ist ebenfalls nicht bestimmbar. Neue Konfigurationsdateien legt das Update nicht an; der geänderte Repositoryeintrag in composer.json (A7) ist beim Rollback zusammen mit composer.lock auf den Stand von 7.0.8 zurückzunehmen, andernfalls löst die Bauumgebung eine Abhängigkeit auf, die die ältere Codebasis nicht erwartet.
Plugin-Entwickler
Wer im eigenen Plugin das Ereignis newDirectRequest verarbeitet und den Parameter function an method_exists() weiterreicht, sollte das Muster aus A1 übernehmen: eine ausdrückliche Freigabeliste der aufrufbaren Methoden und eine Trennung zwischen lesenden und schreibenden Aufrufen. Eigener Code, der application.libraries.admin.progressbar importiert, muss vor dem Update ersetzt werden, da die Bibliothek entfernt wurde (siehe Weitere relevante Änderungen). Wer gegen die OpenAPI-Bibliothek entwickelt oder eine eigene composer.json pflegt, muss den neuen VCS-Repositoryeintrag übernehmen (A7).
Theme-Entwickler
Keine der vollständig beschriebenen Änderungen betrifft Themes unmittelbar. Relevant sind die Einträge unter Weitere relevante Änderungen: Der Kopfbereich von fruity_twentythree erzeugt die Regel für das Häkchensymbol nur noch bei gesetztem Wert, das Benutzerraster erhält Inline-Stile für die Datumsfilter, die Anzeigedauer der Meldungen wurde erhöht, und die Weiterleitung am Umfrageende trägt jetzt target und rel. Abgeleitete Themes und eigene CSS-Regeln, die auf die bisherige DOM-Struktur oder auf die bisherigen Zeitwerte bauen, sind gegen diese Punkte zu prüfen.
Integratoren
Automatisierung, die den direkten Plugin-Endpunkt verwendet, auf die freigegebenen Methodennamen und auf POST für datenverändernde Aufrufe umstellen (A1). Skripte, die den Dialog für Dummy-Teilnehmer befüllen, auf den neuen Platzhalter anpassen (A6). Werkzeuge, die Fragedaten über den Editor-Endpunkt abrufen, mit einem Konto betreiben, das Leserechte auf den Umfrageinhalt besitzt (A4). Auswertungen, die Statistikausgaben verschlüsselter numerischer Felder weiterverarbeiten, auf die geänderte Zeilenstruktur anpassen (A8). Auf PostgreSQL nach dem Update prüfen, dass Antworten wieder gespeichert werden (A2); bei Aufrufen der Vorlagen-API hinter einem Proxy die verwendete Basisadresse kontrollieren (A3).
API-Nutzer
Den Vorlagen-Endpunkt der REST-Schnittstelle nach dem Update gegen eine aktive Umfrage aufrufen und bestätigen, dass die gerenderte Vorlage weiterhin ausgeliefert wird; in Aufbauten mit abweichendem Host-Header kann sich das Ergebnis gegenüber 7.0.8 ändern (A3). Wer die OpenAPI-Beschreibung der Schnittstelle abruft oder generiert, sollte sie nach dem Umstieg auf die geänderte Bibliothek einmal vollständig gegen den eigenen Client validieren (A7). Nutzer der RemoteControl-Schnittstelle finden unter Weitere relevante Änderungen die Korrektur an get_question_properties, die den sprachabhängigen Standardwert nun zurückliefert.