XMPP: geen input-validatie in XmppSettings en test-connection dialoog — ongeldige input bereikt de connectie #1432

Closed
opened 2026-08-09 18:39:35 +00:00 by brenno · 0 comments
Owner

Bevinding

Twee aanverwante tekortkomingen aan de trust-grens waar gebruikersinput de XMPP-stack bereikt.

1. XmppSettings is een pure data-klasse zonder validatie

lib/models/xmpp_settings.dart — de constructor (regels 13–19) accepteert elke waarde zonder checks:

  • Server-URL: geen validatie dat het een geldige wss://-URI is. De endpoint getter (regel 44–48) retourneert null bij een onparseerbare URI, maar dat wordt pas in openXmppFrameTransport gecontroleerd (regel 20–22) — de gebruiker ziet dan een cryptische XmppConnectException.
  • Domain: als serverUrl geen geldige URI is en domainOverride leeg is, retourneert de domain getter (regel 62–67) een lege string. Een lege domain wordt naar de XMPP-server gestuurd in de <open to="">-frame, wat de server weigert met een onduidelijke fout.
  • Localpart: de localpart getter (regel 54–57) doet geen SCRAM-escaping of validatie. De SASL-laag (xmpp_sasl.dart regel 152–153) doet de escaping wel (=→=3D, ,→=2C), maar als de localpart karakters bevat die niet in SASL-name mogen (bijv. null-bytes), kan dat onverwacht gedrag geven.
  • pinnedCertSha256: geen validatie dat het een geldige hex-string is van de juiste lengte (64 chars voor SHA-256). Een ongeldige hash wordt doorgegeven aan NetGuard.pinnedCertCheck, die waarschijnlijk faalt met een cryptische fout.

2. De test-connection dialoog stuurt ruwe input direct door

lib/widgets/dialogs/xmpp_test_connection_dialog.dart — de _test-methode (regels 150–169) construeert XmppSettings met ongetrimde/ongevalideerde input:

final settings = XmppSettings(
  serverUrl: _server.text.trim(),
  jid: _jid.text.trim(),
);
final outcome = await widget.connect(
  settings,
  _password.text,  // niet eens getrimd!
  _conference.text.trim(),
);

Er is:

  • Geen URL-validatie op de server (een lege of ongeldige URL bereikt openXmppFrameTransport)
  • Geen JID-formaat-validatie (een lege of ongeldig JID bereikt de SASL-laag)
  • Geen password-lengte-check (een leeg password wordt naar SCRAM gestuurd)
  • Geen conference-URL-validatie (een ongeldige URL bereikt companionRoomJid)

De gebruiker ziet dan een van de XmppSessionFailure-codes, maar de mapping naar een begrijpelijke foutmelding ontbreekt voor input-fouten (de failure-codes zijn ontworpen voor server-fouten, niet voor "je hebt geen URL ingevuld").

Trust boundary

Gebruikersinput → Applicatie (XmppSettings → XMPP-stack). Dit is precies de trust-grens die de security-architect-skill noemt: "Welke invoer wordt nu vertrouwd die dat eerder niet was?"

Impact

  • Ongeldige input bereikt de XMPP-stack en produceert cryptische, niet-gelokaliseerde foutmeldingen.
  • Een lege domain in de <open to="">-frame kan de server in een ondefinieerbare staat brengen.
  • Een ongeldige pinnedCertSha256 kan de certificaat-pinning onbedoeld uitschakelen (afhankelijk van hoe NetGuard.pinnedCertCheck met ongeldige input omgaat).
  • De gebruiker heeft geen feedback over wat hij verkeerd heeft ingevuld.

Oplossingsrichting

  1. Voeg een validate()-methode toe aan XmppSettings die een XmppSettingsValidationError-enum retourneert (of null bij geldig). Check: niet-lege server-URL, geldige wss://-URI, niet-lege domain, geldige JID-indeling (localpart@domain), geldige hex voor pinnedCertSha256.
  2. Valideer in de dialoog vóór _liveConnectTest: als settings.validate() een fout retourneert, toon een gelokaliseerde foutmelding en ga niet naar de connectie.
  3. Aanvullend: overweeg een XmppSettings.fromJid(String jid, String serverUrl) factory die de JID parseert en de domain afleidt, in plaats van de getters die late parsing doen.

Locatie

  • lib/models/xmpp_settings.dart regels 13–19 (constructor), 44–48 (endpoint), 54–57 (localpart), 62–67 (domain)
  • lib/widgets/dialogs/xmpp_test_connection_dialog.dart regels 150–169 (_test-methode)

Severity

MEDIUM — ongeldige input bereikt de stack; cryptische fouten in plaats van gelokaliseerde validatie.

## Bevinding Twee aanverwante tekortkomingen aan de trust-grens waar gebruikersinput de XMPP-stack bereikt. ### 1. XmppSettings is een pure data-klasse zonder validatie `lib/models/xmpp_settings.dart` — de constructor (regels 13–19) accepteert elke waarde zonder checks: - **Server-URL:** geen validatie dat het een geldige `wss://`-URI is. De `endpoint` getter (regel 44–48) retourneert `null` bij een onparseerbare URI, maar dat wordt pas in `openXmppFrameTransport` gecontroleerd (regel 20–22) — de gebruiker ziet dan een cryptische `XmppConnectException`. - **Domain:** als `serverUrl` geen geldige URI is en `domainOverride` leeg is, retourneert de `domain` getter (regel 62–67) een lege string. Een lege domain wordt naar de XMPP-server gestuurd in de `<open to="">`-frame, wat de server weigert met een onduidelijke fout. - **Localpart:** de `localpart` getter (regel 54–57) doet geen SCRAM-escaping of validatie. De SASL-laag (`xmpp_sasl.dart` regel 152–153) doet de escaping wel (`=→=3D`, `,→=2C`), maar als de localpart karakters bevat die niet in SASL-name mogen (bijv. null-bytes), kan dat onverwacht gedrag geven. - **pinnedCertSha256:** geen validatie dat het een geldige hex-string is van de juiste lengte (64 chars voor SHA-256). Een ongeldige hash wordt doorgegeven aan `NetGuard.pinnedCertCheck`, die waarschijnlijk faalt met een cryptische fout. ### 2. De test-connection dialoog stuurt ruwe input direct door `lib/widgets/dialogs/xmpp_test_connection_dialog.dart` — de `_test`-methode (regels 150–169) construeert `XmppSettings` met ongetrimde/ongevalideerde input: ```dart final settings = XmppSettings( serverUrl: _server.text.trim(), jid: _jid.text.trim(), ); final outcome = await widget.connect( settings, _password.text, // niet eens getrimd! _conference.text.trim(), ); ``` Er is: - Geen URL-validatie op de server (een lege of ongeldige URL bereikt `openXmppFrameTransport`) - Geen JID-formaat-validatie (een lege of ongeldig JID bereikt de SASL-laag) - Geen password-lengte-check (een leeg password wordt naar SCRAM gestuurd) - Geen conference-URL-validatie (een ongeldige URL bereikt `companionRoomJid`) De gebruiker ziet dan een van de `XmppSessionFailure`-codes, maar de mapping naar een begrijpelijke foutmelding ontbreekt voor input-fouten (de failure-codes zijn ontworpen voor server-fouten, niet voor "je hebt geen URL ingevuld"). ### Trust boundary Gebruikersinput → Applicatie (XmppSettings → XMPP-stack). Dit is precies de trust-grens die de security-architect-skill noemt: "Welke invoer wordt nu vertrouwd die dat eerder niet was?" ### Impact - Ongeldige input bereikt de XMPP-stack en produceert cryptische, niet-gelokaliseerde foutmeldingen. - Een lege domain in de `<open to="">`-frame kan de server in een ondefinieerbare staat brengen. - Een ongeldige `pinnedCertSha256` kan de certificaat-pinning onbedoeld uitschakelen (afhankelijk van hoe `NetGuard.pinnedCertCheck` met ongeldige input omgaat). - De gebruiker heeft geen feedback over wat hij verkeerd heeft ingevuld. ### Oplossingsrichting 1. **Voeg een `validate()`-methode toe aan `XmppSettings`** die een `XmppSettingsValidationError`-enum retourneert (of null bij geldig). Check: niet-lege server-URL, geldige `wss://`-URI, niet-lege domain, geldige JID-indeling (localpart@domain), geldige hex voor `pinnedCertSha256`. 2. **Valideer in de dialoog vóór `_liveConnectTest`:** als `settings.validate()` een fout retourneert, toon een gelokaliseerde foutmelding en ga niet naar de connectie. 3. **Aanvullend:** overweeg een `XmppSettings.fromJid(String jid, String serverUrl)` factory die de JID parseert en de domain afleidt, in plaats van de getters die late parsing doen. ### Locatie - `lib/models/xmpp_settings.dart` regels 13–19 (constructor), 44–48 (endpoint), 54–57 (localpart), 62–67 (domain) - `lib/widgets/dialogs/xmpp_test_connection_dialog.dart` regels 150–169 (_test-methode) ### Severity MEDIUM — ongeldige input bereikt de stack; cryptische fouten in plaats van gelokaliseerde validatie.
brenno 2026-08-09 20:56:41 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
LibreKAT/Ocideck#1432
No description provided.