These examples target the published version 1.5.0. See the verified downloads. Features marked 1.5 are new in this release.
import org.owasp.encoder.Encode;
out.write("<p>");
Encode.forHtmlContent(out, userText);
out.write("</p><input value=\"");
Encode.forHtmlAttribute(out, userText);
out.write("\">");out is a java.io.Writer owned by the caller; handle its IOException normally.
String-returning calls such as Encode.forHtmlAttribute(userText) have the same
context contract. Do not reuse this result for JavaScript, CSS or a URL component.
Avoid double escaping with frameworks that already escape HTML output.
The 1.5 JavaScript block, CDATA and XML-comment encoders protect the boundary on both sides of each nonempty encoded fragment. Ordinary composition remains supported:
out.write("<script>const message = \"trusted prefix: ");
Encode.forJavaScriptBlock(out, userText);
out.write("\";</script>");
out.write("<value><![CDATA[trusted prefix: ");
Encode.forCDATA(out, userText);
out.write("]]></value>");
out.write("<!-- trusted prefix: ");
Encode.forXmlComment(out, userText);
out.write(" -->");The trusted prefix and suffix must themselves be valid syntax. Keep the encoder
matched to the actual parser: forJavaScriptBlock and the general
forJavaScript protect HTML script raw text; forJavaScriptAttribute is for a
quoted event-handler attribute, and forJavaScriptSource is for a standalone
resource.
This correction changes emitted text. HTML-script JavaScript uses additional
hex escapes (including \x2d for hyphen and escapes for both cases of the
letters in script) while preserving the JavaScript string value. CDATA
preserves parsed XML text but can expand each ] or > to 13 characters and
can change SAX/StAX event boundaries. XML-comment encoding replaces every
hyphen with ~ and therefore does not preserve comment text. Review snapshots,
signatures, cache keys and code that inspects encoded bytes. Prefer Writer APIs
for large or high-expansion CDATA values.
For a same-origin search URL with a fixed trusted path and one raw query value:
String url = "/search?q=" + Encode.forUriComponent(query) + "&page=1";
out.write("<a href=\"");
Encode.forHtmlAttribute(out, url);
out.write("\">Search</a>");For an entire untrusted URL, apply application-specific validation before
forHtmlAttribute: parse with java.net.URI, allow-list schemes (often https
and http), and enforce destination/path restrictions. Parsing alone is not
validation; rejecting or allowing relative URLs is an application decision. Do
not pass a whole URL to forUriComponent, or assume deprecated forUri validates
one. A reusable validator cannot be inferred without the application's rules.
Choose the adapter matching the container's javax or jakarta namespace;
never install both taglib JARs together. For Jakarta:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="e" uri="owasp.encoder.jakarta" %>
<p>Function: ${e:forHtmlContent(param.message)}</p>
<p>Tag: <e:forHtmlContent value="${param.message}" /></p>
<input value="${e:forHtmlAttribute(param.message)}">For a javax container, replace the taglib directive with:
<%@ taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>The basic identifiers above and their advanced equivalents are stable lookup
identifiers; a browser need not be able to fetch them. Advanced identifiers:
owasp.encoder.jakarta.advanced and
https://www.owasp.org/index.php/OWASP_Java_Encoder_Project#advanced.
Use only the basic or advanced declaration for a given prefix.
On 1.5, both basic taglibs contain these tags and same-named EL functions:
forCDATA, forHtml, forHtmlContent, forHtmlAttribute,
forHtmlUnquotedAttribute, forJavaScript, forJson, forCssString, forCssUrl,
forUri, forUriComponent, forXml, forXmlContent, forXmlAttribute, forXml11.
Advanced adds forJavaScriptAttribute, forJavaScriptBlock, forJavaScriptSource,
forXmlComment, forXml11Content and forXml11Attribute. forJava is intentionally
absent. Through 1.4.1, neither taglib contains forJson or any forXml11*
binding, even though XML 1.1 already exists in the core API. XML 1.1 bindings must
output an actual XML 1.1 document, not an HTML page.
All tags require the value attribute and an empty body. The container evaluates
the attribute as a String before the tag calls its Writer encoder; a missing EL
value can therefore become an empty String, unlike the facade's null-to-"null"
behavior. Plain ${param.message} is not automatically HTML-escaped by JSP.
Do not evaluate returned strings as EL again, including via framework helpers
that perform a second expression evaluation.
EL availability and defaults depend on the container and deployment descriptor;
legacy descriptors or isELIgnored="true" can disable it. Configure a compatible
JSP/EL version and enable EL deliberately, as in the example. Do not treat raw
${...} appearing on a page as successful encoding. See the
Jakarta Pages specification
and the packaged JSP engine checks.
The explicit module name for core is owasp.encoder. After verifying and obtaining
encoder-1.5.0.jar, put that unchanged JAR in lib/, then create:
src/example.app/module-info.java:
module example.app {
requires owasp.encoder;
}src/example.app/example/Main.java:
package example;
import org.owasp.encoder.Encode;
public class Main {
public static void main(String[] args) {
System.out.println(Encode.forHtmlContent("<hello>"));
}
}With JDK 17:
javac --module-path lib --module-source-path src -d out -m example.app
java --module-path lib:out -m example.app/example.MainExpected output: <hello>. On Windows use lib;out for the runtime module
path. Keep unrelated JARs out of lib/. Adapter modules additionally require their
API modules; follow the module/API and OSGi tables.
Automatic fallback names differ deliberately and are not aliases of the explicit
names. The consumer harness exercises
both discovery modes on original JARs.