Skip to content

Commit dab4f52

Browse files
ifradeomsohn
authored andcommitted
ManifestParser: Do not accept DOCTYPE and entities
These open the door for XXE attacks [1] and manifest do not need them. [1] https://en.wikipedia.org/wiki/XML_external_entity_attack Change-Id: Ia79971e1c34afaf287584ae4a7f71baebcb48b6a
1 parent 46a6378 commit dab4f52

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@
1212
import static java.nio.charset.StandardCharsets.UTF_8;
1313
import static org.junit.Assert.assertEquals;
1414
import static org.junit.Assert.assertNull;
15+
import static org.junit.Assert.assertThrows;
1516
import static org.junit.Assert.assertTrue;
1617
import static org.junit.Assert.fail;
1718

1819
import java.io.ByteArrayInputStream;
20+
import java.io.File;
1921
import java.io.IOException;
2022
import java.net.URI;
23+
import java.nio.file.Files;
24+
import java.nio.file.StandardOpenOption;
2125
import java.util.HashSet;
2226
import java.util.Map;
2327
import java.util.Set;
@@ -221,4 +225,33 @@ public void testNormalizeEmptyPath() {
221225
testNormalize("", "");
222226
testNormalize("a/b", "a/b");
223227
}
228+
229+
@Test
230+
public void testXXE() throws Exception {
231+
File externalEntity = File.createTempFile("injected", "xml");
232+
externalEntity.deleteOnExit();
233+
Files.write(externalEntity.toPath(),
234+
"<evil>injected xml</evil>"
235+
.getBytes(UTF_8),
236+
StandardOpenOption.WRITE);
237+
String baseUrl = "https://git.google.com/";
238+
StringBuilder xmlContent = new StringBuilder();
239+
xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
240+
.append("<!DOCTYPE booo [ <!ENTITY foobar SYSTEM \"")
241+
.append(externalEntity.getPath()).append("\"> ]>\n")
242+
.append("<manifest>")
243+
.append("<remote name=\"remote1\" fetch=\".\" />")
244+
.append("<default revision=\"master\" remote=\"remote1\" />")
245+
.append("&foobar;")
246+
.append("<project path=\"foo\" name=\"foo\" groups=\"a,test\" />")
247+
.append("</manifest>");
248+
249+
IOException e = assertThrows(IOException.class,
250+
() -> new ManifestParser(null, null, "master", baseUrl, null,
251+
null)
252+
.read(new ByteArrayInputStream(
253+
xmlContent.toString().getBytes(UTF_8))));
254+
assertTrue(e.getCause().getMessage().contains("DOCTYPE"));
255+
}
256+
224257
}

org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,17 @@ public void read(InputStream inputStream) throws IOException {
142142
xmlInRead++;
143143
final XMLReader xr;
144144
try {
145-
xr = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
145+
SAXParserFactory spf = SAXParserFactory.newInstance();
146+
spf.setFeature(
147+
"http://xml.org/sax/features/external-general-entities", //$NON-NLS-1$
148+
false);
149+
spf.setFeature(
150+
"http://xml.org/sax/features/external-parameter-entities", //$NON-NLS-1$
151+
false);
152+
spf.setFeature(
153+
"http://apache.org/xml/features/disallow-doctype-decl", //$NON-NLS-1$
154+
true);
155+
xr = spf.newSAXParser().getXMLReader();
146156
} catch (SAXException | ParserConfigurationException e) {
147157
throw new IOException(JGitText.get().noXMLParserAvailable, e);
148158
}

0 commit comments

Comments
 (0)