diff --git a/README.md b/README.md index faf4cb9..49b8761 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,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 --------------------- @@ -225,6 +228,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: the JSP, Jakarta and ESAPI bundles now declare the core versions they need (`[1.5,2)` for the tags, which call `Encode.forJson`; `[1.4.1,2)` for ESAPI) and the JSP API ranges they support, instead of unversioned imports that could wire to an older core and fail when a tag ran. Bundle symbolic names are now declared explicitly and unchanged [#137](https://github.com/OWASP/owasp-java-encoder/issues/137). * 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). 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..b40b586 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. Encodes control characters the same way + as 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. Encodes control + characters the same way as 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. Encodes control + characters the same way as 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. Encodes control characters the same way + as 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..6ec5ed3 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. Encodes control characters the same way + as 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. Encodes control + characters the same way as 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. Encodes control + characters the same way as 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. Encodes control characters the same way + as 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()) {