1515
1616import static ch .qos .logback .core .CoreConstants .XML_PARSING ;
1717
18+ import java .io .ByteArrayInputStream ;
1819import java .io .IOException ;
1920import java .io .InputStream ;
2021import java .util .ArrayList ;
4041
4142public class SaxEventRecorder extends DefaultHandler implements ContextAware {
4243
44+ // org.xml.sax.ext.LexicalHandler is an optional interface
4345 final ContextAwareImpl contextAwareImpl ;
4446 final ElementPath elementPath ;
4547 List <SaxEvent > saxEventList = new ArrayList <SaxEvent >();
4648 Locator locator ;
4749
50+
4851 public SaxEventRecorder (Context context ) {
4952 this (context , new ElementPath ());
5053 }
5154
55+
5256 public SaxEventRecorder (Context context , ElementPath elementPath ) {
5357 contextAwareImpl = new ContextAwareImpl (context , this );
5458 this .elementPath = elementPath ;
5559 }
5660
61+ /**
62+ * An implementation which disallows external DTDs
63+ *
64+ * @param publicId The public identifier, or null if none is
65+ * available.
66+ * @param systemId The system identifier provided in the XML
67+ * document.
68+ * @return
69+ * @throws SAXException
70+ * @throws IOException
71+ * @since 1.5.13
72+ */
73+ @ Override
74+ public InputSource resolveEntity (String publicId , String systemId ) throws SAXException , IOException {
75+ addWarn ("Document Type Declaration (DOCTYPE) with external file reference is" );
76+ addWarn ("disallowed to prevent Server-Side Request Forgery (SSRF) attacks." );
77+ addWarn ("returning contents of SYSTEM " +systemId + " as a white space" );
78+ return new InputSource (new ByteArrayInputStream (" " .getBytes ()));
79+ }
80+
5781 final public void recordEvents (InputStream inputStream ) throws JoranException {
5882 recordEvents (new InputSource (inputStream ));
5983 }
6084
6185 public void recordEvents (InputSource inputSource ) throws JoranException {
6286 SAXParser saxParser = buildSaxParser ();
6387 try {
88+ // the following sax property can be set in order to add 'this' as LexicalHandler to the saxParser
89+ // However, this is not needed as long as resolveEntity() method is implemented as above
90+ // saxParser.setProperty("http://xml.org/sax/properties/lexical-handler", this);
91+
6492 saxParser .parse (inputSource , this );
93+
6594 return ;
6695 } catch (IOException ie ) {
6796 handleError ("I/O error occurred while parsing xml file" , ie );
@@ -83,7 +112,7 @@ private SAXParser buildSaxParser() throws JoranException {
83112 try {
84113 SAXParserFactory spf = SAXParserFactory .newInstance ();
85114 spf .setValidating (false );
86- // spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
115+ //spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
87116 // See LOGBACK-1465
88117 spf .setFeature ("http://xml.org/sax/features/external-general-entities" , false );
89118 spf .setFeature ("http://xml.org/sax/features/external-parameter-entities" , false );
@@ -93,11 +122,11 @@ private SAXParser buildSaxParser() throws JoranException {
93122 String errMsg = "Error during SAX paser configuration. See https://logback.qos.ch/codes.html#saxParserConfiguration" ;
94123 addError (errMsg , pce );
95124 throw new JoranException (errMsg , pce );
96- } catch (SAXException pce ) {
125+ } catch (SAXException pce ) {
97126 String errMsg = "Error during parser creation or parser configuration" ;
98127 addError (errMsg , pce );
99128 throw new JoranException (errMsg , pce );
100- }
129+ }
101130 }
102131
103132 public void startDocument () {
@@ -116,7 +145,6 @@ protected boolean shouldIgnoreForElementPath(String tagName) {
116145 }
117146
118147 public void startElement (String namespaceURI , String localName , String qName , Attributes atts ) {
119-
120148 String tagName = getTagName (localName , qName );
121149 if (!shouldIgnoreForElementPath (tagName )) {
122150 elementPath .push (tagName );
@@ -169,20 +197,17 @@ String getTagName(String localName, String qName) {
169197 }
170198
171199 public void error (SAXParseException spe ) throws SAXException {
172- addError (XML_PARSING + " - Parsing error on line " + spe .getLineNumber () + " and column "
173- + spe .getColumnNumber ());
200+ addError (XML_PARSING + " - Parsing error on line " + spe .getLineNumber () + " and column " + spe .getColumnNumber ());
174201 addError (spe .toString ());
175202 }
176203
177204 public void fatalError (SAXParseException spe ) throws SAXException {
178- addError (XML_PARSING + " - Parsing fatal error on line " + spe .getLineNumber () + " and column "
179- + spe .getColumnNumber ());
205+ addError (XML_PARSING + " - Parsing fatal error on line " + spe .getLineNumber () + " and column " + spe .getColumnNumber ());
180206 addError (spe .toString ());
181207 }
182208
183209 public void warning (SAXParseException spe ) throws SAXException {
184- addWarn (XML_PARSING + " - Parsing warning on line " + spe .getLineNumber () + " and column "
185- + spe .getColumnNumber (), spe );
210+ addWarn (XML_PARSING + " - Parsing warning on line " + spe .getLineNumber () + " and column " + spe .getColumnNumber (), spe );
186211 }
187212
188213 public void addError (String msg ) {
0 commit comments