Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,32 @@ 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"%> |

Migrating from forUri
---------------------

`Encode.forUri`, the `uri` context (`Encoders.URI`), `ForUriTag`, and the `forUri`
tag and EL function are deprecated. Percent-encoding a complete URI does not make an
untrusted URI safe: `forUri("javascript:alert(1)")` is returned unchanged. It also
always encodes `%`, so an already percent-encoded URI is double-encoded.

- For an untrusted value inserted into a URL (a path segment, a query parameter name
or value, or a fragment), use `forUriComponent`:

```jsp
<a href="/search?q=<%=Encode.forUriComponent(query)%>&amp;page=1">
```

- For an entire untrusted URL, parse it with `java.net.URI`, allow-list its scheme
(for example `http` and `https`, rejecting a missing scheme unless relative URLs are
intended), and then encode the whole value for the enclosing context:

```jsp
<a href="<%=Encode.forHtmlAttribute(validatedUri.toString())%>">
```

`forUri` is retained for compatibility in all 1.x releases. Whether 2.0 removes it is
tracked in [#142](https://github.com/OWASP/owasp-java-encoder/issues/142).

Development
-----------

Expand All @@ -167,6 +193,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.
* 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 `&#133;`, 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 `&#x85;` and U+2028 (line separator) as `&#x2028;`, so they are not normalized to a line feed [#136](https://github.com/OWASP/owasp-java-encoder/issues/136).
* maintenance: clarify output-context contracts and expand XML 1.1 tests, fix clean reactor compilation, and remove the obsolete benchmark profile.
Expand Down
18 changes: 14 additions & 4 deletions core/src/main/java/org/owasp/encoder/Encode.java
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,16 @@ public static void forCssUrl(Writer out, String input)
*
* @param input the input to encode
* @return the encoded result
* @deprecated Encoding a complete URI does not make an untrusted URI
* safe. Encode each untrusted value inserted into a URL with
* {@link #forUriComponent(String)} instead. To use an entire untrusted
* URL, parse it with {@link java.net.URI}, allow-list its scheme (for
* example {@code http} and {@code https}), and then encode it for the
* enclosing output context, for example with
* {@link #forHtmlAttribute(String)}. This method always encodes
* {@code %}, so never apply it to a URI that is already percent-encoded.
* It is retained for compatibility in all 1.x releases; removal in 2.0 is
* under consideration.
*/
@Deprecated public static String forUri(String input) {
return encode(Encoders.URI_ENCODER, input);
Expand All @@ -704,7 +714,7 @@ public static void forCssUrl(Writer out, String input)
* @throws NullPointerException if out is null
* @throws IOException if thrown by writer
*
* @deprecated There is never a need to encode a complete URI with this form of encoding.
* @deprecated See {@link #forUri(String)} for what to use instead.
*/
@Deprecated public static void forUri(Writer out, String input)
throws IOException
Expand Down Expand Up @@ -735,9 +745,9 @@ public static void forCssUrl(Writer out, String input)
* <b>Encoding Notes</b>
* <ul>
*
* <li>Unlike {@link #forUri(String)} this method is safe to be
* used in most containing contexts, including: HTML/XML, CSS,
* and JavaScript contexts.</li>
* <li>The output contains only unreserved characters and
* {@code %xx} escapes, so it is safe to be used in most containing
* contexts, including: HTML/XML, CSS, and JavaScript contexts.</li>
*
* <li>URL encoding is an encoding for bytes, not unicode. The
* input string is thus first encoded as a sequence of UTF-8
Expand Down
13 changes: 12 additions & 1 deletion core/src/main/java/org/owasp/encoder/Encoders.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,15 @@ public final class Encoders {
public static final String JSON = "json";
/**
* Name of {@linkplain Encode#forUri(String) URI} context.
*/
*
* @deprecated Encoding a complete URI does not make an untrusted URI
* safe. Use {@link #URI_COMPONENT} for each untrusted value inserted
* into a URL, or validate an entire URL with {@link java.net.URI} and an
* allow-listed scheme before encoding it for the enclosing context. See
* {@link Encode#forUri(String)}. Retained for compatibility in all 1.x
* releases.
*/
@Deprecated
public static final String URI = "uri";
/**
* Name of {@linkplain Encode#forUriComponent(String) URI component}
Expand Down Expand Up @@ -274,6 +282,9 @@ private static <T extends Encoder> T map(String name, T encoder) {
* Returns the shared stateless Encoder singleton for the specified context.
* The returned instance is thread-safe. Context names are case-sensitive.
*
* <p>The deprecated {@code "uri"} context ({@link #URI}) is still
* recognized for compatibility.</p>
*
* @param contextName the context name (one of the String constants defined
* in this class)
* @return an encoder for the specified context.
Expand Down
14 changes: 14 additions & 0 deletions core/src/test/java/org/owasp/encoder/EncodersTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,20 @@ public void testForNameIsNotNull() throws Exception {
assertTrue(count > 0);
}

/**
* The "uri" context is deprecated everywhere Encode.forUri is, but stays
* usable for compatibility.
*/
public void testUriContextIsDeprecatedButRetained() throws Exception {
assertTrue(Encoders.class.getField("URI").isAnnotationPresent(Deprecated.class));
assertTrue(Encode.class.getMethod("forUri", String.class)
.isAnnotationPresent(Deprecated.class));
assertTrue(Encode.class.getMethod("forUri", java.io.Writer.class, String.class)
.isAnnotationPresent(Deprecated.class));
assertFalse(Encoders.class.getField("URI_COMPONENT").isAnnotationPresent(Deprecated.class));
assertSame(Encoders.URI_ENCODER, Encoders.forName("uri"));
}

public void testJsonContext() throws Exception {
assertEquals("json", Encoders.JSON);
Encoder encoder = Encoders.forName(Encoders.JSON);
Expand Down
4 changes: 4 additions & 0 deletions esapi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Name the call sites of deprecated core APIs such as Encode.forUri. -->
<showDeprecation>true</showDeprecation>
</configuration>
<executions>
<execution>
<id>compile-module-path-test-support</id>
Expand Down
4 changes: 4 additions & 0 deletions jakarta/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Name the call sites of deprecated core APIs such as Encode.forUri. -->
<showDeprecation>true</showDeprecation>
</configuration>
<executions>
<execution>
<id>compile-module-path-test-support</id>
Expand Down
5 changes: 5 additions & 0 deletions jakarta/src/main/java/org/owasp/encoder/tag/ForUriTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@
* This wraps the {@link org.owasp.encoder.Encode#forUri(java.lang.String)}.
*
* @author Jeremy Long (jeremy.long@gmail.com)
* @deprecated Use {@link ForUriComponentTag} for each untrusted value
* inserted into a URL. See
* {@link org.owasp.encoder.Encode#forUri(java.lang.String)} for how to handle
* an entire untrusted URL. Retained for compatibility in all 1.x releases.
*/
@Deprecated
public class ForUriTag extends EncodingTag {
@Override
public void doTag() throws JspException, IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@
particularly dangerous context to put untrusted content in, as for
example a "javascript:" URL provided by a malicious user would be
"properly" escaped, and still execute.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context. Always encodes %, so never apply it to an already percent-encoded URI.
</description>
<display-name>forUri</display-name>
<name>forUri</name>
Expand Down Expand Up @@ -469,7 +469,7 @@
particularly dangerous context to put untrusted content in, as for
example a "javascript:" URL provided by a malicious user would be
"properly" escaped, and still execute.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context. Always encodes %, so never apply it to an already percent-encoded URI.
</description>
<display-name>forUri</display-name>
<name>forUri</name>
Expand Down
4 changes: 2 additions & 2 deletions jakarta/src/main/resources/META-INF/java-encoder.tld
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@
particularly dangerous context to put untrusted content in, as for
example a "javascript:" URL provided by a malicious user would be
"properly" escaped, and still execute.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context. Always encodes %, so never apply it to an already percent-encoded URI.
</description>
<display-name>forUri</display-name>
<name>forUri</name>
Expand Down Expand Up @@ -364,7 +364,7 @@
particularly dangerous context to put untrusted content in, as for
example a "javascript:" URL provided by a malicious user would be
"properly" escaped, and still execute.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context. Always encodes %, so never apply it to an already percent-encoded URI.
</description>
<display-name>forUri</display-name>
<name>forUri</name>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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 junit.framework.TestCase;

/**
* ForUriTag is deprecated like Encode.forUri, and its replacement is not.
*/
public class ForUriTagDeprecationTest extends TestCase {

@SuppressWarnings("deprecation") // the test inspects the deprecated tag
public void testForUriTagIsDeprecated() {
assertTrue(ForUriTag.class.isAnnotationPresent(Deprecated.class));
assertFalse(ForUriComponentTag.class.isAnnotationPresent(Deprecated.class));
}
}
4 changes: 4 additions & 0 deletions jsp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Name the call sites of deprecated core APIs such as Encode.forUri. -->
<showDeprecation>true</showDeprecation>
</configuration>
<executions>
<execution>
<id>compile-module-path-test-support</id>
Expand Down
5 changes: 5 additions & 0 deletions jsp/src/main/java/org/owasp/encoder/tag/ForUriTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@
* This wraps the {@link org.owasp.encoder.Encode#forUri(java.lang.String)}.
*
* @author Jeremy Long (jeremy.long@gmail.com)
* @deprecated Use {@link ForUriComponentTag} for each untrusted value
* inserted into a URL. See
* {@link org.owasp.encoder.Encode#forUri(java.lang.String)} for how to handle
* an entire untrusted URL. Retained for compatibility in all 1.x releases.
*/
@Deprecated
public class ForUriTag extends EncodingTag {
@Override
public void doTag() throws JspException, IOException {
Expand Down
4 changes: 2 additions & 2 deletions jsp/src/main/resources/META-INF/java-encoder-advanced.tld
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@
particularly dangerous context to put untrusted content in, as for
example a "javascript:" URL provided by a malicious user would be
"properly" escaped, and still execute.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context. Always encodes %, so never apply it to an already percent-encoded URI.
</description>
<display-name>forUri</display-name>
<name>forUri</name>
Expand Down Expand Up @@ -469,7 +469,7 @@
particularly dangerous context to put untrusted content in, as for
example a "javascript:" URL provided by a malicious user would be
"properly" escaped, and still execute.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context. Always encodes %, so never apply it to an already percent-encoded URI.
</description>
<display-name>forUri</display-name>
<name>forUri</name>
Expand Down
4 changes: 2 additions & 2 deletions jsp/src/main/resources/META-INF/java-encoder.tld
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@
particularly dangerous context to put untrusted content in, as for
example a "javascript:" URL provided by a malicious user would be
"properly" escaped, and still execute.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context. Always encodes %, so never apply it to an already percent-encoded URI.
</description>
<display-name>forUri</display-name>
<name>forUri</name>
Expand Down Expand Up @@ -361,7 +361,7 @@
particularly dangerous context to put untrusted content in, as for
example a "javascript:" URL provided by a malicious user would be
"properly" escaped, and still execute.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context.
Deprecated: prefer java.net.URI when working with complete URIs and forUriComponent for individual inserted components. Validate the URL scheme before use and apply encoding for the enclosing output context. Always encodes %, so never apply it to an already percent-encoded URI.
</description>
<display-name>forUri</display-name>
<name>forUri</name>
Expand Down
Loading
Loading