Mittel

ApostropheCMS import-export tar guard misses './..' because it is a literal '../' substring test

  • Veröffentlicht: 20.10.2026
  • Aktualisiert: 20.10.2026 21:35

Zusammenfassung

Der Tar-Extraktionsschutz, der in @apostrophecms/import-export für GHSA-mwxc-m426-3f78 hinzugefügt wurde, ist eine literale Teilstring-Prüfung auf ../, und ./.. enthält diesen Teilstring nicht. Ein Archiveintrag namens ./.. passiert daher die Überprüfung, path.join normalisiert ihn auf das übergeordnete Verzeichnis des Exportverzeichnisses, und der resultierende fs.WriteStream öffnet ein Verzeichnis und gibt EISDIR ohne registrierten error-Listener aus, was den Node-Prozess beendet.

Bestätigt auf default-branch HEAD 1bd5d0a7a6fe880836fa75adad6964f1c577d640, Paketversion 3.6.2.

Details

packages/import-export/lib/formats/gzip.js, im Tar-Stream-Handler entry innerhalb von extract(filepath, exportPath):

js
const name = header.name.replace(/\\/g, '/');
if (name.includes('../')) {
  // skipped
}
...
stream.pipe(fs.WriteStream(path.join(exportPath, name)));

In diesen vier Zeilen liegen zwei separate Probleme. Die Schutzprüfung testet den rohen Eintragsnamen auf einen Teilstring, anstatt den zusammengefügten Pfad aufzulösen und eine Pfadgrenzenprüfung (Containment) zu erzwingen; zudem verfügt der Schreib-Stream über keinen error-Handler, sodass jeder Stream-Fehler zu einem unbehandelten 'error'-Ereignis wird.

Um die Schwachstelle zu erreichen, ist lediglich ein Konto mit Importberechtigung erforderlich. packages/import-export/modules/@apostrophecms/import-export-page/index.js stellt post.importExportImport bereit, das lib/methods/import.js aufruft; dieser Handler erfordert req.user und ruft danach format.input(exportPath) auf, was für einen .gz-Upload darin besteht, dass gzip.js die Funktion extract() auf das hochgeladene Archiv anwendet.

PoC

Hierbei handelt es sich nicht um einen End-to-End-Exploit. Im Folgenden werden die drei Primitiven aufgeführt, von denen der Absturz abhängt, jeweils einzeln ausgeführt, zusammen mit einem Trace der Route auf Quellcodeebene. Die Kette von post.importExportImport bis extract() wurde im Quellcode nachvollzogen, nicht live beobachtet.

Der Schutz übersieht die Payload:

bash
node -e "console.log('./..'.includes('../')); console.log('..'.includes('../')); console.log('a/./..'.includes('../'));"
false
false
false

path.join löst den Pfad anschließend außerhalb des Exportverzeichnisses auf:

bash
node -e "const path=require('path'); const exportPath='/tmp/exportRoot'; console.log(path.join(exportPath,'./..'));"
/tmp

Und ein Schreib-Stream, der auf einem Verzeichnis ohne error-Listener geöffnet wird, beendet den Prozess, anstatt die Anfrage fehlschlagen zu lassen:

bash
node -e "const fs=require('fs'); const s=fs.createWriteStream('/tmp'); s.write('x'); s.end(); setTimeout(()=>console.log('still alive'),500);"
events.js:291
      throw er; // Unhandled 'error' event
      ^

Error: EISDIR: illegal operation on a directory, open '/tmp'
Emitted 'error' event on WriteStream instance at:
    at internal/fs/streams.js:361:12
    at FSReqCallback.oncomplete (fs.js:156:23) {
  errno: -21,
  code: 'EISDIR',
  syscall: 'open',
  path: '/tmp'
}

Der Frame events.js:291 zeigt, dass die Ausgabe von der Node-14-Zeile des Testsystems stammt. Das Verhalten bei unbehandelten error-Ereignissen ist nicht versionsspezifisch, die genaue Fehlermeldung auf den jeweils unterstützten Node-Versionen sollte jedoch geprüft werden.

Bestätigung auf Quellcodeebene ohne Programmausführung:

bash
grep -n "includes('../')" packages/import-export/lib/formats/gzip.js
grep -n "WriteStream" packages/import-export/lib/formats/gzip.js

Auswirkungen

Ein authentifizierter Benutzer mit Zugriff auf die Import-Benutzeroberfläche kann ein manipuliertes Archiv hochladen und den verarbeitenden Node-Prozess zum Absturz bringen. Jeder Worker-Prozess, der ein solches Archiv verarbeitet, stürzt auf die gleiche Weise ab.

Vorgeschlagene Behebung

Das Ziel auflösen, die Pfadeingrenzung erzwingen und einen Fehler-Handler anfügen:

js
const base = path.resolve(exportPath);
const target = path.resolve(path.join(exportPath, name));

if (target !== base && !target.startsWith(base + path.sep)) {
  stream.on('end', next);
  stream.resume();
  return;
}

if (header.type === 'directory') {
  fsp.mkdir(target).then(next).catch(reject);
} else {
  const out = fs.WriteStream(target);
  out.on('error', reject);
  stream.pipe(out);
  stream.on('end', next);
}

Der Error-Handler ist unabhängig davon sinnvoll: Jeder Tar-Eintrag, der auf einem bestehenden Verzeichnisnamen landet, hat denselben Effekt, unabhängig davon, ob eine Pfadüberquerung vorliegt.

Warum dies nicht GHSA-mwxc-m426-3f78 ist

Die Überprüfung name.includes('../') ist die Fehlerbehebung, die für GHSA-mwxc-m426-3f78 / CVE-2026-32731 bereitgestellt wurde. Sie blockiert Namen, die die literale Zeichenfolge ../ enthalten. Sie kanonisiert jedoch nicht den zusammengefügten Pfad, sodass ./.. und ein einfaches .. weiterhin passieren, und sie behebt nicht den fehlenden error-Listener. Dieser Bericht befasst sich mit den verbleibenden Lücken der Teilstring-Prüfung.

KI-Unterstützung wurde für das Code-Audit und die Ausarbeitung verwendet. Die genauen Guard- und WriteStream-Zeilen in packages/import-export/lib/formats/gzip.js beim angegebenen HEAD wurden manuell verifiziert, die Import-Route vom Seitenmodul über lib/methods/import.js in den Eintrags-Handler wurde manuell nachverfolgt und die drei Node-Einzeiler wurden manuell ausgeführt und wortwörtlich übernommen.

Was zu tun ist

Aktualisieren Sie @apostrophecms/import-export auf Version 3.7.0 oder höher.

Betroffene Software

Klicken Sie auf eine Technologie, um alle zugehörigen Schwachstellen anzuzeigen.

PlattformPaketAnfällige VersionenBehoben in
npm-Paket @apostrophecms/import-export < 3.7.0 3.7.0

Verweise

CVSS-Wert -
CVSS-Vektor
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N
Schwäche (CWE)
CWE-22
Plattform
npm
Paket
@apostrophecms/import-export
Veröffentlicht
20.10.2026
Aktualisiert
20.10.2026 21:35

Quellen und Lizenzen · Von DockRay bearbeitet oder übersetzt; Rechte und Lizenzen der Quellen bleiben erhalten.

OSV / GitHub Advisory Database - GHSA-97wv-p4xx-c7mg - CC BY 4.0

Schwachstellenhistorie: @apostrophecms/import-export

Alle veröffentlichten Schwachstellen dieses Pakets (npm-Paket), neueste zuerst. Zeigt, ob es ein einmaliger Ausrutscher ist oder ein Paket, das man im Auge behalten muss.

Einträge insgesamt
4
Erste → letzte
03.2026 10.2026
Ohne Fix
0
In Angriffen ausgenutzt
0

Verteilung nach Schweregrad

  • Kritisch 1
  • Mittel 3

Veröffentlichungen pro Jahr

  1. 2026: 4
  1. ApostropheCMS import-export tar guard misses './..' because it is a literal '../' substring test dieser Eintrag
    Mittel CVE-2026-113664 < 3.7.0 3.7.0

Erkennen Sie Schwachstellen in Ihrer Anwendung

Mit der DockRay-Integration und aktivierter Softwareinventarisierung prüft DockRay gemeldete Komponentenversionen auf bekannte Schwachstellen und benachrichtigt Sie über bestätigte Treffer. Die Abdeckung hängt von der unterstützten Technologie und den verfügbaren Meldungen ab.

Anwendung verbinden
DockRay Newsletter

Anwendungssicherheit in Ihrem Postfach

Wichtige Schwachstellen, konkrete Empfehlungen und praktische Tipps für Ihre Anwendungen. Wählen Sie Ihre Technologien und verfolgen Sie, was für Ihr Projekt relevant ist.

  • Eine tägliche Zusammenfassung neuer Schwachstellen, auch kritischer.
  • Benachrichtigungen über wichtige Updates.
  • Praktische Tipps zur Sicherheit und Überwachung von Anwendungen.

Leer lassen, um Meldungen zu allen Technologien zu erhalten.

Kostenlos anmelden. In jeder E-Mail mit einem Klick abmelden.