From bb049777bc4caaf0f71717cce8dcc9d036d18baf Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 10 Feb 2026 12:36:54 +0100 Subject: [PATCH] IDEA-385732 XXE in UI Designer Form Parser Allows Arbitrary File Read via Malicious Project GitOrigin-RevId: db767d4248b9dfacdf51838204cb541e420e9feb --- .../intellij/uiDesigner/compiler/Utils.java | 25 ++++++++++++++++--- .../uiDesigner/CutCopyPasteSupport.java | 8 ++---- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java index 3dd3d0f32c03..8b9777c06d3a 100644 --- a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java +++ b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/Utils.java @@ -11,6 +11,7 @@ import com.intellij.uiDesigner.lw.LwRootContainer; import com.intellij.uiDesigner.lw.PropertiesProvider; import org.jdom.Document; import org.jdom.input.SAXBuilder; +import org.jetbrains.annotations.NotNull; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -41,13 +42,29 @@ public final class Utils { private static SAXParser createParser() { try { - return SAXParserFactory.newInstance().newSAXParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + try { + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + } + catch (Exception ignored) { + } + return factory.newSAXParser(); } catch (Exception e) { return null; } } + private static @NotNull SAXBuilder createBuilder() { + SAXBuilder builder = new SAXBuilder(); + builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + builder.setFeature("http://xml.org/sax/features/external-general-entities", false); + builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + return builder; + } + /** * @param provider if null, no classes loaded and no properties read */ @@ -56,7 +73,7 @@ public final class Utils { throw new AlienFormFileException(); } - final Document document = new SAXBuilder().build(new StringReader(formFileContent), "UTF-8"); + final Document document = createBuilder().build(new StringReader(formFileContent), "UTF-8"); return getRootContainerFromDocument(document, provider); } @@ -70,7 +87,7 @@ public final class Utils { * @throws Exception if there is a problem with parsing DOM */ public static LwRootContainer getRootContainer(final URL formFile, final PropertiesProvider provider) throws Exception { - final Document document = new SAXBuilder().build(formFile); + final Document document = createBuilder().build(formFile); return getRootContainerFromDocument(document, provider); } @@ -90,7 +107,7 @@ public final class Utils { } public static LwRootContainer getRootContainer(final InputStream stream, final PropertiesProvider provider) throws Exception { - final Document document = new SAXBuilder().build(stream, "UTF-8"); + final Document document = createBuilder().build(stream, "UTF-8"); return getRootContainerFromDocument(document, provider); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/CutCopyPasteSupport.java b/plugins/ui-designer/src/com/intellij/uiDesigner/CutCopyPasteSupport.java index 394e1358e92d..9582bd1ee918 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/CutCopyPasteSupport.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/CutCopyPasteSupport.java @@ -10,6 +10,7 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ide.CopyPasteManager; +import com.intellij.openapi.util.JDOMUtil; import com.intellij.uiDesigner.compiler.Utils; import com.intellij.uiDesigner.designSurface.GuiEditor; import com.intellij.uiDesigner.lw.LwComponent; @@ -17,9 +18,7 @@ import com.intellij.uiDesigner.lw.LwContainer; import com.intellij.uiDesigner.radComponents.RadComponent; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; -import org.jdom.Document; import org.jdom.Element; -import org.jdom.input.SAXBuilder; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,7 +33,6 @@ import java.util.List; public final class CutCopyPasteSupport implements CopyProvider, CutProvider, PasteProvider{ private static final Logger LOG = Logger.getInstance(CutCopyPasteSupport.class); - private static final SAXBuilder SAX_BUILDER = new SAXBuilder(); private final GuiEditor myEditor; private static final @NonNls String ELEMENT_SERIALIZED = "serialized"; @@ -139,10 +137,8 @@ public final class CutCopyPasteSupport implements CopyProvider, CutProvider, Pas final PsiPropertiesProvider provider = new PsiPropertiesProvider(editor.getModule()); try { - //noinspection HardCodedStringLiteral - final Document document = SAX_BUILDER.build(new StringReader(serializedComponents), "UTF-8"); + final Element rootElement = JDOMUtil.load(new StringReader(serializedComponents)); - final Element rootElement = document.getRootElement(); if (!rootElement.getName().equals(ELEMENT_SERIALIZED)) { return false; }