From 4804ab06e04e6494cb577fb101f9b0531a8d6f00 Mon Sep 17 00:00:00 2001 From: Volodymyr Borysenko Date: Fri, 25 Sep 2026 20:58:49 -0700 Subject: [PATCH 1/2] Add XML 1.1 tags and EL functions to both taglibs (#131) The XML 1.1 encoders added in 1.4.0 were not reachable from either taglib. Add ForXml11Tag, ForXml11ContentTag and ForXml11AttributeTag to jsp and jakarta, mirroring the XML 1.0 tags and identical apart from the javax/jakarta imports. Declare all three as tags and EL functions in both advanced TLDs, next to their XML 1.0 counterparts, and add forXml11 to both basic TLDs next to forXml. TaglibDescriptorTest's exclusion list is now exactly {forJava}, and the pinned basic set includes forXml11. TagEncodingTest picks up the new tags from the advanced TLD, covering null, hostile Unicode and buffer-boundary inputs against the Encode facade. The README states why forJava has no tag and adds a News entry. --- README.md | 4 + .../encoder/tag/ForXml11AttributeTag.java | 50 ++++++++++ .../owasp/encoder/tag/ForXml11ContentTag.java | 50 ++++++++++ .../org/owasp/encoder/tag/ForXml11Tag.java | 50 ++++++++++ .../META-INF/java-encoder-advanced.tld | 94 +++++++++++++++++++ .../main/resources/META-INF/java-encoder.tld | 36 +++++++ .../encoder/tag/TaglibDescriptorTest.java | 12 +-- .../encoder/tag/ForXml11AttributeTag.java | 50 ++++++++++ .../owasp/encoder/tag/ForXml11ContentTag.java | 50 ++++++++++ .../org/owasp/encoder/tag/ForXml11Tag.java | 50 ++++++++++ .../META-INF/java-encoder-advanced.tld | 94 +++++++++++++++++++ .../main/resources/META-INF/java-encoder.tld | 36 +++++++ .../encoder/tag/TaglibDescriptorTest.java | 12 +-- 13 files changed, 576 insertions(+), 12 deletions(-) create mode 100644 jakarta/src/main/java/org/owasp/encoder/tag/ForXml11AttributeTag.java create mode 100644 jakarta/src/main/java/org/owasp/encoder/tag/ForXml11ContentTag.java create mode 100644 jakarta/src/main/java/org/owasp/encoder/tag/ForXml11Tag.java create mode 100644 jsp/src/main/java/org/owasp/encoder/tag/ForXml11AttributeTag.java create mode 100644 jsp/src/main/java/org/owasp/encoder/tag/ForXml11ContentTag.java create mode 100644 jsp/src/main/java/org/owasp/encoder/tag/ForXml11Tag.java diff --git a/README.md b/README.md index 801a876..4ebe4b4 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,9 @@ TagLib | encoder-jakarta-jsp | <%@taglib prefix="e" uri="owasp.encoder.jakarta"%> | | encoder-jsp | <%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project"%> | +Every `Encode.forX(String)` context has a tag and an EL function in the advanced +taglib, except `forJava`: Java source generation is not a JSP output context. + Migrating from forUri --------------------- @@ -205,6 +208,7 @@ Development builds use `1.5.0-SNAPSHOT`; this is not a published release. * feat: all four `forJavaScript*` methods encode dollar sign (`$`) as `\x24`, backtick as `\x60`, and opening brace (`{`) as `\x7b` [#129](https://github.com/OWASP/owasp-java-encoder/issues/129). Escaping `{` prevents input after a trusted `$` from completing `${...}`. Encoded output now supports literal text in ordinary (untagged) template literals as well as single- and double-quoted strings. This changes the encoded output while preserving its decoded JavaScript string value. Tagged templates (including `String.raw`), `${...}` expression bodies, JSON, and script URLs are unsupported; each method's HTML context restrictions still apply. * fix: all four `forJavaScript*` methods escape unpaired UTF-16 surrogates as `\uXXXX`, preserving their JavaScript string values through UTF-8 serialization [#135](https://github.com/OWASP/owasp-java-encoder/issues/135), and escape DEL/C1 controls (U+007F to U+009F) as `\xNN` [#163](https://github.com/OWASP/owasp-java-encoder/issues/163). Valid surrogate pairs and other non-ASCII text remain unescaped except U+2028/U+2029. These are output-fidelity changes; NEL was already ordinary JavaScript string data. * feat: add `Encode.forJson` String/Writer methods, the `json` encoder context, and `forJson` tags and EL functions in both JSP and Jakarta tag libraries [#145](https://github.com/OWASP/owasp-java-encoder/issues/145). The caller supplies double quotes. Output uses RFC 8259 string escapes and also escapes HTML script delimiters. Java `null` becomes the text `null` (the JSON string `"null"` when quoted); unpaired surrogates use Unicode escapes and may not interoperate with every JSON consumer. Prefer a serializer for complete JSON documents. The ESAPI adapter retains its existing JSON delegation and null behavior. +* feat: add `forXml11`, `forXml11Content` and `forXml11Attribute` tags and EL functions to the advanced JSP and Jakarta taglibs, and `forXml11` to the basic taglibs [#131](https://github.com/OWASP/owasp-java-encoder/issues/131). * deprecation: `Encoders.URI` and both `ForUriTag` classes are now deprecated like `Encode.forUri`, whose Javadoc now says what to use instead; the `forUri` TLD descriptions warn about double encoding, the adapter builds show deprecation call sites, and the README has a [forUri migration section](#migrating-from-foruri) [#130](https://github.com/OWASP/owasp-java-encoder/issues/130). * fix: `forHtmlUnquotedAttribute` now replaces U+0085 (NEL) with a hyphen like the other C1 control characters, instead of emitting `…`, which HTML5 parsers decode as U+2026 [#136](https://github.com/OWASP/owasp-java-encoder/issues/136). * fix: the XML 1.1 encoders (`forXml11`, `forXml11Content`, `forXml11Attribute`) now encode U+0085 (NEL) as `…` and U+2028 (line separator) as `
`, so they are not normalized to a line feed [#136](https://github.com/OWASP/owasp-java-encoder/issues/136). diff --git a/jakarta/src/main/java/org/owasp/encoder/tag/ForXml11AttributeTag.java b/jakarta/src/main/java/org/owasp/encoder/tag/ForXml11AttributeTag.java new file mode 100644 index 0000000..bd93b63 --- /dev/null +++ b/jakarta/src/main/java/org/owasp/encoder/tag/ForXml11AttributeTag.java @@ -0,0 +1,50 @@ +// Copyright (c) 2026 OWASP +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// * Neither the name of the OWASP nor the names of its +// contributors may be used to endorse or promote products +// derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.owasp.encoder.tag; + +import java.io.IOException; +import jakarta.servlet.jsp.JspException; +import org.owasp.encoder.Encode; + +/** + * A tag to perform XML 1.1 Attribute Encoding. + * This wraps the {@link org.owasp.encoder.Encode#forXml11Attribute(java.lang.String)}. + */ +public class ForXml11AttributeTag extends EncodingTag { + @Override + public void doTag() throws JspException, IOException { + Encode.forXml11Attribute(getJspContext().getOut(), _value); + } +} diff --git a/jakarta/src/main/java/org/owasp/encoder/tag/ForXml11ContentTag.java b/jakarta/src/main/java/org/owasp/encoder/tag/ForXml11ContentTag.java new file mode 100644 index 0000000..dba7058 --- /dev/null +++ b/jakarta/src/main/java/org/owasp/encoder/tag/ForXml11ContentTag.java @@ -0,0 +1,50 @@ +// Copyright (c) 2026 OWASP +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// * Neither the name of the OWASP nor the names of its +// contributors may be used to endorse or promote products +// derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.owasp.encoder.tag; + +import java.io.IOException; +import jakarta.servlet.jsp.JspException; +import org.owasp.encoder.Encode; + +/** + * A tag to perform XML 1.1 Content Encoding. + * This wraps the {@link org.owasp.encoder.Encode#forXml11Content(java.lang.String)}. + */ +public class ForXml11ContentTag extends EncodingTag { + @Override + public void doTag() throws JspException, IOException { + Encode.forXml11Content(getJspContext().getOut(), _value); + } +} diff --git a/jakarta/src/main/java/org/owasp/encoder/tag/ForXml11Tag.java b/jakarta/src/main/java/org/owasp/encoder/tag/ForXml11Tag.java new file mode 100644 index 0000000..7ad54ea --- /dev/null +++ b/jakarta/src/main/java/org/owasp/encoder/tag/ForXml11Tag.java @@ -0,0 +1,50 @@ +// Copyright (c) 2026 OWASP +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// * Neither the name of the OWASP nor the names of its +// contributors may be used to endorse or promote products +// derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.owasp.encoder.tag; + +import java.io.IOException; +import jakarta.servlet.jsp.JspException; +import org.owasp.encoder.Encode; + +/** + * A tag to perform XML 1.1 Encoding. + * This wraps the {@link org.owasp.encoder.Encode#forXml11(java.lang.String)}. + */ +public class ForXml11Tag extends EncodingTag { + @Override + public void doTag() throws JspException, IOException { + Encode.forXml11(getJspContext().getOut(), _value); + } +} diff --git a/jakarta/src/main/resources/META-INF/java-encoder-advanced.tld b/jakarta/src/main/resources/META-INF/java-encoder-advanced.tld index 0480e14..fa4eb82 100644 --- a/jakarta/src/main/resources/META-INF/java-encoder-advanced.tld +++ b/jakarta/src/main/resources/META-INF/java-encoder-advanced.tld @@ -56,6 +56,23 @@ java.lang.String + + + Encodes for XML 1.1 attribute content. Control characters are encoded as for + forXml11. Use only in XML 1.1 documents. + + forXml11Attribute + forXml11Attribute + org.owasp.encoder.tag.ForXml11AttributeTag + empty + + value to be written out + value + true + true + java.lang.String + + Encodes for XML and XHTML. forXml @@ -70,6 +87,27 @@ java.lang.String + + + Encodes for XML 1.1 text content and attributes. Like forXml, but the control + characters XML 1.1 allows only as character references (U+0001 to U+0008, U+000B, + U+000C, U+000E to U+001F and U+007F to U+009F) are written as references such as + &#x01;, and NEL (U+0085) and U+2028 are written as &#x85; and &#x2028; so an + XML 1.1 processor does not normalize them to a line feed. Use only in XML 1.1 + documents: XML 1.0 does not allow these character references. + + forXml11 + forXml11 + org.owasp.encoder.tag.ForXml11Tag + empty + + value to be written out + value + true + true + java.lang.String + + Encodes a JavaScript string for HTML event attributes (such as onclick), HTML script @@ -350,6 +388,24 @@ java.lang.String + + + Encodes XML 1.1 text content. Does not escape quotes and is unsafe for attribute + values; use forXml11 or forXml11Attribute for those contexts. Control characters are + encoded as for forXml11. Use only in XML 1.1 documents. + + forXml11Content + forXml11Content + org.owasp.encoder.tag.ForXml11ContentTag + empty + + value to be written out + value + true + true + java.lang.String + + Performs percent-encoding for a component of a URI, such as a query @@ -498,6 +554,21 @@ java.lang.String forXml(java.lang.String) forXml(unsafeData) + + + Encodes for XML 1.1 text content and attributes. Like forXml, but the control + characters XML 1.1 allows only as character references (U+0001 to U+0008, U+000B, + U+000C, U+000E to U+001F and U+007F to U+009F) are written as references such as + &#x01;, and NEL (U+0085) and U+2028 are written as &#x85; and &#x2028; so an + XML 1.1 processor does not normalize them to a line feed. Use only in XML 1.1 + documents: XML 1.0 does not allow these character references. + + forXml11 + forXml11 + org.owasp.encoder.Encode + java.lang.String forXml11(java.lang.String) + forXml11(unsafeData) + Encodes XML and XHTML text content. Does not escape quotes and is unsafe for attribute values; use forXml or forXmlAttribute for those contexts. @@ -508,6 +579,18 @@ java.lang.String forXmlContent(java.lang.String) forXmlContent(unsafeData) + + + Encodes XML 1.1 text content. Does not escape quotes and is unsafe for attribute + values; use forXml11 or forXml11Attribute for those contexts. Control characters are + encoded as for forXml11. Use only in XML 1.1 documents. + + forXml11Content + forXml11Content + org.owasp.encoder.Encode + java.lang.String forXml11Content(java.lang.String) + forXml11Content(unsafeData) + Encodes for XML and XHTML attribute content. forXmlAttribute @@ -516,6 +599,17 @@ java.lang.String forXmlAttribute(java.lang.String) forXmlAttribute(unsafeData) + + + Encodes for XML 1.1 attribute content. Control characters are encoded as for + forXml11. Use only in XML 1.1 documents. + + forXml11Attribute + forXml11Attribute + org.owasp.encoder.Encode + java.lang.String forXml11Attribute(java.lang.String) + forXml11Attribute(unsafeData) + Encoder for XML comments. NOT FOR USE WITH (X)HTML CONTEXTS. diff --git a/jakarta/src/main/resources/META-INF/java-encoder.tld b/jakarta/src/main/resources/META-INF/java-encoder.tld index a4c56d9..621bfbd 100644 --- a/jakarta/src/main/resources/META-INF/java-encoder.tld +++ b/jakarta/src/main/resources/META-INF/java-encoder.tld @@ -73,6 +73,27 @@ java.lang.String + + + Encodes for XML 1.1 text content and attributes. Like forXml, but the control + characters XML 1.1 allows only as character references (U+0001 to U+0008, U+000B, + U+000C, U+000E to U+001F and U+007F to U+009F) are written as references such as + &#x01;, and NEL (U+0085) and U+2028 are written as &#x85; and &#x2028; so an + XML 1.1 processor does not normalize them to a line feed. Use only in XML 1.1 + documents: XML 1.0 does not allow these character references. + + forXml11 + forXml11 + org.owasp.encoder.tag.ForXml11Tag + empty + + value to be written out + value + true + true + java.lang.String + + Encodes a JavaScript string for HTML event attributes (such as onclick), HTML script @@ -393,6 +414,21 @@ java.lang.String forXml(java.lang.String) forXml(unsafeData) + + + Encodes for XML 1.1 text content and attributes. Like forXml, but the control + characters XML 1.1 allows only as character references (U+0001 to U+0008, U+000B, + U+000C, U+000E to U+001F and U+007F to U+009F) are written as references such as + &#x01;, and NEL (U+0085) and U+2028 are written as &#x85; and &#x2028; so an + XML 1.1 processor does not normalize them to a line feed. Use only in XML 1.1 + documents: XML 1.0 does not allow these character references. + + forXml11 + forXml11 + org.owasp.encoder.Encode + java.lang.String forXml11(java.lang.String) + forXml11(unsafeData) + Encodes XML and XHTML text content. Does not escape quotes and is unsafe for attribute values; use forXml or forXmlAttribute for those contexts. diff --git a/jakarta/src/test/java/org/owasp/encoder/tag/TaglibDescriptorTest.java b/jakarta/src/test/java/org/owasp/encoder/tag/TaglibDescriptorTest.java index 9fa7664..2c08222 100644 --- a/jakarta/src/test/java/org/owasp/encoder/tag/TaglibDescriptorTest.java +++ b/jakarta/src/test/java/org/owasp/encoder/tag/TaglibDescriptorTest.java @@ -105,13 +105,13 @@ static Taglib load(String resource) throws Exception { } /** - * Java source generation is not a JSP context. XML 1.1 tags are tracked - * separately in issue #131. Deprecated forUri remains for compatibility; - * deprecation alone must not silently remove a deployed tag/function. + * Java source generation is not a JSP context, so forJava is the only + * facade method without a tag and function. Deprecated forUri remains for + * compatibility; deprecation alone must not silently remove a deployed + * tag/function. */ public void testAdvancedMatchesSupportedFacade() throws Exception { - Set unsupported = new TreeSet(Arrays.asList( - "forJava", "forXml11", "forXml11Content", "forXml11Attribute")); + Set unsupported = new TreeSet(Arrays.asList("forJava")); Set expected = new TreeSet(); for (Method method : Encode.class.getMethods()) { if (Modifier.isStatic(method.getModifiers()) && method.getName().startsWith("for") @@ -214,7 +214,7 @@ public void testBasicIsSubsetOfAdvanced() throws Exception { Set expectedBasic = new TreeSet(Arrays.asList( "forCDATA", "forCssString", "forCssUrl", "forHtml", "forHtmlAttribute", "forHtmlContent", "forHtmlUnquotedAttribute", "forJavaScript", "forJson", - "forUri", "forUriComponent", "forXml", "forXmlAttribute", "forXmlContent")); + "forUri", "forUriComponent", "forXml", "forXml11", "forXmlAttribute", "forXmlContent")); assertEquals("basic tags", expectedBasic, basic.tagClasses.keySet()); assertEquals("basic functions", expectedBasic, basic.functionSignatures.keySet()); for (Map.Entry tag : basic.tagClasses.entrySet()) { diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForXml11AttributeTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForXml11AttributeTag.java new file mode 100644 index 0000000..0a87d68 --- /dev/null +++ b/jsp/src/main/java/org/owasp/encoder/tag/ForXml11AttributeTag.java @@ -0,0 +1,50 @@ +// Copyright (c) 2026 OWASP +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// * Neither the name of the OWASP nor the names of its +// contributors may be used to endorse or promote products +// derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.owasp.encoder.tag; + +import java.io.IOException; +import javax.servlet.jsp.JspException; +import org.owasp.encoder.Encode; + +/** + * A tag to perform XML 1.1 Attribute Encoding. + * This wraps the {@link org.owasp.encoder.Encode#forXml11Attribute(java.lang.String)}. + */ +public class ForXml11AttributeTag extends EncodingTag { + @Override + public void doTag() throws JspException, IOException { + Encode.forXml11Attribute(getJspContext().getOut(), _value); + } +} diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForXml11ContentTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForXml11ContentTag.java new file mode 100644 index 0000000..8c0d859 --- /dev/null +++ b/jsp/src/main/java/org/owasp/encoder/tag/ForXml11ContentTag.java @@ -0,0 +1,50 @@ +// Copyright (c) 2026 OWASP +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// * Neither the name of the OWASP nor the names of its +// contributors may be used to endorse or promote products +// derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.owasp.encoder.tag; + +import java.io.IOException; +import javax.servlet.jsp.JspException; +import org.owasp.encoder.Encode; + +/** + * A tag to perform XML 1.1 Content Encoding. + * This wraps the {@link org.owasp.encoder.Encode#forXml11Content(java.lang.String)}. + */ +public class ForXml11ContentTag extends EncodingTag { + @Override + public void doTag() throws JspException, IOException { + Encode.forXml11Content(getJspContext().getOut(), _value); + } +} diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForXml11Tag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForXml11Tag.java new file mode 100644 index 0000000..d8572e5 --- /dev/null +++ b/jsp/src/main/java/org/owasp/encoder/tag/ForXml11Tag.java @@ -0,0 +1,50 @@ +// Copyright (c) 2026 OWASP +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// * Neither the name of the OWASP nor the names of its +// contributors may be used to endorse or promote products +// derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. + +package org.owasp.encoder.tag; + +import java.io.IOException; +import javax.servlet.jsp.JspException; +import org.owasp.encoder.Encode; + +/** + * A tag to perform XML 1.1 Encoding. + * This wraps the {@link org.owasp.encoder.Encode#forXml11(java.lang.String)}. + */ +public class ForXml11Tag extends EncodingTag { + @Override + public void doTag() throws JspException, IOException { + Encode.forXml11(getJspContext().getOut(), _value); + } +} diff --git a/jsp/src/main/resources/META-INF/java-encoder-advanced.tld b/jsp/src/main/resources/META-INF/java-encoder-advanced.tld index 5217a86..359fea6 100644 --- a/jsp/src/main/resources/META-INF/java-encoder-advanced.tld +++ b/jsp/src/main/resources/META-INF/java-encoder-advanced.tld @@ -56,6 +56,23 @@ java.lang.String + + + Encodes for XML 1.1 attribute content. Control characters are encoded as for + forXml11. Use only in XML 1.1 documents. + + forXml11Attribute + forXml11Attribute + org.owasp.encoder.tag.ForXml11AttributeTag + empty + + value to be written out + value + true + true + java.lang.String + + Encodes for XML and XHTML. forXml @@ -70,6 +87,27 @@ java.lang.String + + + Encodes for XML 1.1 text content and attributes. Like forXml, but the control + characters XML 1.1 allows only as character references (U+0001 to U+0008, U+000B, + U+000C, U+000E to U+001F and U+007F to U+009F) are written as references such as + &#x01;, and NEL (U+0085) and U+2028 are written as &#x85; and &#x2028; so an + XML 1.1 processor does not normalize them to a line feed. Use only in XML 1.1 + documents: XML 1.0 does not allow these character references. + + forXml11 + forXml11 + org.owasp.encoder.tag.ForXml11Tag + empty + + value to be written out + value + true + true + java.lang.String + + Encodes a JavaScript string for HTML event attributes (such as onclick), HTML script @@ -350,6 +388,24 @@ java.lang.String + + + Encodes XML 1.1 text content. Does not escape quotes and is unsafe for attribute + values; use forXml11 or forXml11Attribute for those contexts. Control characters are + encoded as for forXml11. Use only in XML 1.1 documents. + + forXml11Content + forXml11Content + org.owasp.encoder.tag.ForXml11ContentTag + empty + + value to be written out + value + true + true + java.lang.String + + Performs percent-encoding for a component of a URI, such as a query @@ -498,6 +554,21 @@ java.lang.String forXml(java.lang.String) forXml(unsafeData) + + + Encodes for XML 1.1 text content and attributes. Like forXml, but the control + characters XML 1.1 allows only as character references (U+0001 to U+0008, U+000B, + U+000C, U+000E to U+001F and U+007F to U+009F) are written as references such as + &#x01;, and NEL (U+0085) and U+2028 are written as &#x85; and &#x2028; so an + XML 1.1 processor does not normalize them to a line feed. Use only in XML 1.1 + documents: XML 1.0 does not allow these character references. + + forXml11 + forXml11 + org.owasp.encoder.Encode + java.lang.String forXml11(java.lang.String) + forXml11(unsafeData) + Encodes XML and XHTML text content. Does not escape quotes and is unsafe for attribute values; use forXml or forXmlAttribute for those contexts. @@ -508,6 +579,18 @@ java.lang.String forXmlContent(java.lang.String) forXmlContent(unsafeData) + + + Encodes XML 1.1 text content. Does not escape quotes and is unsafe for attribute + values; use forXml11 or forXml11Attribute for those contexts. Control characters are + encoded as for forXml11. Use only in XML 1.1 documents. + + forXml11Content + forXml11Content + org.owasp.encoder.Encode + java.lang.String forXml11Content(java.lang.String) + forXml11Content(unsafeData) + Encodes for XML and XHTML attribute content. forXmlAttribute @@ -516,6 +599,17 @@ java.lang.String forXmlAttribute(java.lang.String) forXmlAttribute(unsafeData) + + + Encodes for XML 1.1 attribute content. Control characters are encoded as for + forXml11. Use only in XML 1.1 documents. + + forXml11Attribute + forXml11Attribute + org.owasp.encoder.Encode + java.lang.String forXml11Attribute(java.lang.String) + forXml11Attribute(unsafeData) + Encoder for XML comments. NOT FOR USE WITH (X)HTML CONTEXTS. diff --git a/jsp/src/main/resources/META-INF/java-encoder.tld b/jsp/src/main/resources/META-INF/java-encoder.tld index abfcb7a..a676f0c 100644 --- a/jsp/src/main/resources/META-INF/java-encoder.tld +++ b/jsp/src/main/resources/META-INF/java-encoder.tld @@ -70,6 +70,27 @@ java.lang.String + + + Encodes for XML 1.1 text content and attributes. Like forXml, but the control + characters XML 1.1 allows only as character references (U+0001 to U+0008, U+000B, + U+000C, U+000E to U+001F and U+007F to U+009F) are written as references such as + &#x01;, and NEL (U+0085) and U+2028 are written as &#x85; and &#x2028; so an + XML 1.1 processor does not normalize them to a line feed. Use only in XML 1.1 + documents: XML 1.0 does not allow these character references. + + forXml11 + forXml11 + org.owasp.encoder.tag.ForXml11Tag + empty + + value to be written out + value + true + true + java.lang.String + + Encodes a JavaScript string for HTML event attributes (such as onclick), HTML script @@ -390,6 +411,21 @@ java.lang.String forXml(java.lang.String) forXml(unsafeData) + + + Encodes for XML 1.1 text content and attributes. Like forXml, but the control + characters XML 1.1 allows only as character references (U+0001 to U+0008, U+000B, + U+000C, U+000E to U+001F and U+007F to U+009F) are written as references such as + &#x01;, and NEL (U+0085) and U+2028 are written as &#x85; and &#x2028; so an + XML 1.1 processor does not normalize them to a line feed. Use only in XML 1.1 + documents: XML 1.0 does not allow these character references. + + forXml11 + forXml11 + org.owasp.encoder.Encode + java.lang.String forXml11(java.lang.String) + forXml11(unsafeData) + Encodes XML and XHTML text content. Does not escape quotes and is unsafe for attribute values; use forXml or forXmlAttribute for those contexts. diff --git a/jsp/src/test/java/org/owasp/encoder/tag/TaglibDescriptorTest.java b/jsp/src/test/java/org/owasp/encoder/tag/TaglibDescriptorTest.java index 9fa7664..2c08222 100644 --- a/jsp/src/test/java/org/owasp/encoder/tag/TaglibDescriptorTest.java +++ b/jsp/src/test/java/org/owasp/encoder/tag/TaglibDescriptorTest.java @@ -105,13 +105,13 @@ static Taglib load(String resource) throws Exception { } /** - * Java source generation is not a JSP context. XML 1.1 tags are tracked - * separately in issue #131. Deprecated forUri remains for compatibility; - * deprecation alone must not silently remove a deployed tag/function. + * Java source generation is not a JSP context, so forJava is the only + * facade method without a tag and function. Deprecated forUri remains for + * compatibility; deprecation alone must not silently remove a deployed + * tag/function. */ public void testAdvancedMatchesSupportedFacade() throws Exception { - Set unsupported = new TreeSet(Arrays.asList( - "forJava", "forXml11", "forXml11Content", "forXml11Attribute")); + Set unsupported = new TreeSet(Arrays.asList("forJava")); Set expected = new TreeSet(); for (Method method : Encode.class.getMethods()) { if (Modifier.isStatic(method.getModifiers()) && method.getName().startsWith("for") @@ -214,7 +214,7 @@ public void testBasicIsSubsetOfAdvanced() throws Exception { Set expectedBasic = new TreeSet(Arrays.asList( "forCDATA", "forCssString", "forCssUrl", "forHtml", "forHtmlAttribute", "forHtmlContent", "forHtmlUnquotedAttribute", "forJavaScript", "forJson", - "forUri", "forUriComponent", "forXml", "forXmlAttribute", "forXmlContent")); + "forUri", "forUriComponent", "forXml", "forXml11", "forXmlAttribute", "forXmlContent")); assertEquals("basic tags", expectedBasic, basic.tagClasses.keySet()); assertEquals("basic functions", expectedBasic, basic.functionSignatures.keySet()); for (Map.Entry tag : basic.tagClasses.entrySet()) { From 59edee26c1ac7f4969213adaf77fdb6387933396 Mon Sep 17 00:00:00 2001 From: Volodymyr Borysenko Date: Fri, 25 Sep 2026 22:17:03 -0700 Subject: [PATCH 2/2] Clarify XML 1.1 content and attribute TLD wording Replace "Control characters are encoded as for forXml11" with "Encodes control characters the same way as forXml11" in the forXml11Content and forXml11Attribute tag and function descriptions, as noted in triage. --- .../resources/META-INF/java-encoder-advanced.tld | 16 ++++++++-------- .../resources/META-INF/java-encoder-advanced.tld | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/jakarta/src/main/resources/META-INF/java-encoder-advanced.tld b/jakarta/src/main/resources/META-INF/java-encoder-advanced.tld index fa4eb82..b40b586 100644 --- a/jakarta/src/main/resources/META-INF/java-encoder-advanced.tld +++ b/jakarta/src/main/resources/META-INF/java-encoder-advanced.tld @@ -58,8 +58,8 @@ - Encodes for XML 1.1 attribute content. Control characters are encoded as for - forXml11. Use only in XML 1.1 documents. + Encodes for XML 1.1 attribute content. Encodes control characters the same way + as forXml11. Use only in XML 1.1 documents. forXml11Attribute forXml11Attribute @@ -391,8 +391,8 @@ Encodes XML 1.1 text content. Does not escape quotes and is unsafe for attribute - values; use forXml11 or forXml11Attribute for those contexts. Control characters are - encoded as for forXml11. Use only in XML 1.1 documents. + values; use forXml11 or forXml11Attribute for those contexts. Encodes control + characters the same way as forXml11. Use only in XML 1.1 documents. forXml11Content forXml11Content @@ -582,8 +582,8 @@ Encodes XML 1.1 text content. Does not escape quotes and is unsafe for attribute - values; use forXml11 or forXml11Attribute for those contexts. Control characters are - encoded as for forXml11. Use only in XML 1.1 documents. + values; use forXml11 or forXml11Attribute for those contexts. Encodes control + characters the same way as forXml11. Use only in XML 1.1 documents. forXml11Content forXml11Content @@ -601,8 +601,8 @@ - Encodes for XML 1.1 attribute content. Control characters are encoded as for - forXml11. Use only in XML 1.1 documents. + Encodes for XML 1.1 attribute content. Encodes control characters the same way + as forXml11. Use only in XML 1.1 documents. forXml11Attribute forXml11Attribute diff --git a/jsp/src/main/resources/META-INF/java-encoder-advanced.tld b/jsp/src/main/resources/META-INF/java-encoder-advanced.tld index 359fea6..6ec5ed3 100644 --- a/jsp/src/main/resources/META-INF/java-encoder-advanced.tld +++ b/jsp/src/main/resources/META-INF/java-encoder-advanced.tld @@ -58,8 +58,8 @@ - Encodes for XML 1.1 attribute content. Control characters are encoded as for - forXml11. Use only in XML 1.1 documents. + Encodes for XML 1.1 attribute content. Encodes control characters the same way + as forXml11. Use only in XML 1.1 documents. forXml11Attribute forXml11Attribute @@ -391,8 +391,8 @@ Encodes XML 1.1 text content. Does not escape quotes and is unsafe for attribute - values; use forXml11 or forXml11Attribute for those contexts. Control characters are - encoded as for forXml11. Use only in XML 1.1 documents. + values; use forXml11 or forXml11Attribute for those contexts. Encodes control + characters the same way as forXml11. Use only in XML 1.1 documents. forXml11Content forXml11Content @@ -582,8 +582,8 @@ Encodes XML 1.1 text content. Does not escape quotes and is unsafe for attribute - values; use forXml11 or forXml11Attribute for those contexts. Control characters are - encoded as for forXml11. Use only in XML 1.1 documents. + values; use forXml11 or forXml11Attribute for those contexts. Encodes control + characters the same way as forXml11. Use only in XML 1.1 documents. forXml11Content forXml11Content @@ -601,8 +601,8 @@ - Encodes for XML 1.1 attribute content. Control characters are encoded as for - forXml11. Use only in XML 1.1 documents. + Encodes for XML 1.1 attribute content. Encodes control characters the same way + as forXml11. Use only in XML 1.1 documents. forXml11Attribute forXml11Attribute