Pentest 83.1-83.3: Auto-Import-Pfad härten

83.1 MEDIUM: Auto-Import in syncForwardingForEmail rief
assertValidForwardingEmail nicht auf. Plesk-Member wie
attacker@plesk.internal wären ohne TLD-Block-Check (71.1) in
die DB importiert worden. Fix: jeder importierte Member läuft
durch assertValidForwardingEmail, ungültige werden silent gedroppt
+ auf debug-Level geloggt.

83.2 LOW: Self-Forward-Schutz (81.1) griff nur im Add-Pfad. Wenn
Plesk die eigene Adresse als Mailgroup-Member führte, wäre sie
beim Auto-Import in die DB-Liste gerutscht → nach dem Umschalten
auf Forwarding Mail-Loop. Fix: seenKeys mit der eigenen Adresse
initialisieren bevor die Import-Schleife läuft.

83.3 INFO: PII-Log auf console.debug umgestellt (statt console.log).

Smoke-Test mit gemischter Plesk-Liste: legitimer Member importiert,
reservierte TLDs + Self-Mail (exakt + Plus-Tag) abgelehnt,
Customer-Stamm + Default deduped.
This commit is contained in:
2026-06-18 17:35:17 +02:00
parent a83358bbe6
commit 24e152b201
2 changed files with 46 additions and 4 deletions
@@ -566,6 +566,12 @@ export async function syncForwardingForEmail(
// additionalForwardingEmails-Liste rein. Der nachfolgende Plesk-Call
// deaktiviert dann die Mailgroup und schreibt die volle Liste als
// Forwarding. Verlustfrei kein Empfänger fällt raus.
// Pentest 83.2: Self-Forward auch beim Import blocken. Die
// Stressfrei-Adresse selbst darf nicht aus Plesk in unsere DB
// landen sonst läuft sie nach dem Mailgroup→Forwarding-Umschalten
// als Forwarding-Target auf sich selbst (Mail-Loop).
seenKeys.add(canonicalEmailKey(stressfreiEmail.email));
try {
const pleskState = await checkEmailExists(localPart);
const existingMembers = [
@@ -574,11 +580,26 @@ export async function syncForwardingForEmail(
];
const newImports: string[] = [];
for (const member of existingMembers) {
const key = canonicalEmailKey(member);
// Pentest 83.1: importierte Adressen aus Plesk müssen denselben
// Filter passieren wie User-Eingaben (TLD-Blocklist, Format).
// Sonst rutschen reservierte TLDs wie `.internal` ohne Check
// in unsere DB, falls ein Plesk-Admin sie dort manuell gepflegt
// hat. Ungültige werden silent gedroppt Log informiert.
let validated: string;
try {
validated = assertValidForwardingEmail(member);
} catch (validationErr) {
const reason = validationErr instanceof Error ? validationErr.message : 'unbekannt';
console.debug(
`[syncForwardingForEmail] Plesk-Member "${member}" verworfen: ${reason}`,
);
continue;
}
const key = canonicalEmailKey(validated);
if (!seenKeys.has(key)) {
seenKeys.add(key);
forwardTargets.push(member);
newImports.push(member);
forwardTargets.push(validated);
newImports.push(validated);
}
}
if (newImports.length > 0) {
@@ -590,7 +611,8 @@ export async function syncForwardingForEmail(
where: { id },
data: { additionalForwardingEmails: serializeAdditionalForwards(mergedAdditional) },
});
console.log(
// Pentest 83.3: PII-Logs auf debug-Level statt log-Level.
console.debug(
`[syncForwardingForEmail] Importiert aus Plesk-Mailgroup für ${stressfreiEmail.email}:`,
newImports,
);
+20
View File
@@ -97,6 +97,26 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
## ✅ Erledigt
- [x] **🔒 Pentest 83.1-83.3: Auto-Import-Pfad härten**
- **83.1 MEDIUM:** Auto-Import in `syncForwardingForEmail` umging
`assertValidForwardingEmail`. Plesk-Member wie `attacker@plesk.internal`
oder `evil@x.local` wären ohne TLD-Block-Check (71.1) in unsere
DB gewandert. Fix: jeder importierte Member läuft durch
`assertValidForwardingEmail`; ungültige werden silent gedroppt
und auf `console.debug`-Level geloggt.
- **83.2 LOW:** Self-Forward-Schutz (81.1) lief nur im Add-Pfad.
Wenn Plesk die eigene Adresse als Mailgroup-Member führte, wäre
sie beim Auto-Import in die DB-Liste gerutscht → nach dem
Umschalten auf Forwarding Mail-Loop. Fix:
`seenKeys.add(canonicalEmailKey(stressfreiEmail.email))` vor
der Import-Schleife.
- **83.3 INFO:** PII-Log auf `console.debug` umgestellt (statt
`console.log` auf Default-Level).
- Smoke-Test mit gemischter Plesk-Liste: `karibik61@web.de` (legit)
importiert, `attacker@plesk.internal` + `evil@x.local` per 83.1
abgelehnt, exakte Self-Mail + Plus-Tag-Variante per 83.2
abgelehnt, Customer-Stamm-Mail + Default deduped.
- [x] **🐞 Plesk-Sync: Legacy-Mailgroup-Adressen synchronisierten nicht**
- Prod-Bug: User trägt zusätzliche Weiterleitung ein, Toast meldet
Erfolg, aber Plesk übernimmt nichts. Ursache: Plesk hat zwei