Skip to content

Commit 0b9442b

Browse files
xeno6696claude
andcommitted
Add EncoderTest regression tests for NEL and LINE SEPARATOR encoding
OWASP/owasp-java-encoder#136 reports two fidelity defects in the Java Encoder: forHtmlUnquotedAttribute emits U+0085 (NEL) as &#133;, which HTML5 parsers remap to U+2026 (HORIZONTAL ELLIPSIS), and the XML 1.1 encoders pass U+0085 and U+2028 through raw, which XML 1.1 parsers normalise to LF (a space in attribute values). ESAPI uses its own codecs and is not affected: HTMLEntityCodec replaces every C1 control, NEL included, with &#xfffd;, and XMLEntityCodec emits &#x85; and &#x2028;. These tests lock that behaviour in. The XML test also round-trips the encoded output through the JDK's XML 1.1 parser to confirm both characters survive in element content and attributes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 1556282 commit 0b9442b

1 file changed

Lines changed: 63 additions & 0 deletions

File tree

‎src/test/java/org/owasp/esapi/reference/EncoderTest.java‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@
1818
import static org.junit.Assert.assertNotEquals;
1919

2020
import java.io.IOException;
21+
import java.io.StringReader;
2122
import java.io.UnsupportedEncodingException;
2223
import java.net.URI;
2324
import java.util.ArrayList;
2425
import java.util.Arrays;
2526
import java.util.List;
2627

28+
import javax.xml.XMLConstants;
29+
import javax.xml.parsers.DocumentBuilderFactory;
30+
2731
import org.junit.Ignore;
2832
import org.owasp.esapi.ESAPI;
2933
import org.owasp.esapi.Encoder;
@@ -41,6 +45,8 @@
4145
import org.owasp.esapi.errors.EncodingException;
4246
import org.owasp.esapi.errors.IntrusionException;
4347
import org.owasp.esapi.Randomizer;
48+
import org.w3c.dom.Element;
49+
import org.xml.sax.InputSource;
4450

4551

4652
import junit.framework.Test;
@@ -714,6 +720,63 @@ public void testEncodeForXMLAttributePound() {
714720
assertEquals("&#xa3;", instance.encodeForXMLAttribute("\u00A3"));
715721
}
716722

723+
/**
724+
* Mirrors https://github.com/OWASP/owasp-java-encoder/issues/136 (HTML half).
725+
* An HTML5 parser remaps the numeric reference {@code &#133;} (U+0085, NEL) to
726+
* U+2026 (HORIZONTAL ELLIPSIS) via the windows-1252 table, so NEL must never be
727+
* emitted as that reference. ESAPI replaces every C1 control, NEL included,
728+
* with U+FFFD.
729+
*/
730+
public void testEncodeForHTMLNELIsNotEmittedAsWindows1252Reference() {
731+
System.out.println("encodeForHTMLNELIsNotEmittedAsWindows1252Reference");
732+
Encoder instance = ESAPI.encoder();
733+
String input = "x\u0085y";
734+
735+
String attr = instance.encodeForHTMLAttribute(input);
736+
assertEquals("x&#xfffd;y", attr);
737+
assertFalse(attr.contains("&#133;"));
738+
assertFalse(attr.contains("&#x85;"));
739+
740+
String content = instance.encodeForHTML(input);
741+
assertEquals("x&#xfffd;y", content);
742+
assertFalse(content.contains("&#133;"));
743+
744+
// NEL is treated the same as its C1 neighbours, not singled out.
745+
assertEquals(instance.encodeForHTMLAttribute("x\u0084y"), attr);
746+
assertEquals(instance.encodeForHTMLAttribute("x\u0086y"), attr);
747+
}
748+
749+
/**
750+
* Mirrors https://github.com/OWASP/owasp-java-encoder/issues/136 (XML 1.1 half).
751+
* XML 1.1 section 2.11 normalises raw U+0085 (NEL) and U+2028 (LINE SEPARATOR)
752+
* to LF on input, and attribute-value normalisation then turns that LF into a
753+
* space. Only the character references survive a parse, so both must be
754+
* encoded, and the output must round-trip through a real XML 1.1 parser.
755+
*/
756+
public void testEncodeForXMLNELAndLineSeparatorRoundTripInXml11() throws Exception {
757+
System.out.println("encodeForXMLNELAndLineSeparatorRoundTripInXml11");
758+
Encoder instance = ESAPI.encoder();
759+
760+
assertEquals("x&#x85;y", instance.encodeForXML("x\u0085y"));
761+
assertEquals("x&#x2028;y", instance.encodeForXML("x\u2028y"));
762+
assertEquals("x&#x85;y", instance.encodeForXMLAttribute("x\u0085y"));
763+
assertEquals("x&#x2028;y", instance.encodeForXMLAttribute("x\u2028y"));
764+
765+
String input = "a\u0085b\u2028c";
766+
String xml = "<?xml version=\"1.1\"?><r a=\"" + instance.encodeForXMLAttribute(input) + "\">"
767+
+ instance.encodeForXML(input) + "</r>";
768+
769+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
770+
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
771+
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
772+
Element root = dbf.newDocumentBuilder()
773+
.parse(new InputSource(new StringReader(xml)))
774+
.getDocumentElement();
775+
776+
assertEquals(input, root.getTextContent());
777+
assertEquals(input, root.getAttribute("a"));
778+
}
779+
717780
/**
718781
* Test of encodeForURL method, of class org.owasp.esapi.Encoder.
719782
*

0 commit comments

Comments
 (0)