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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ unchanged. [1.5.1 is available from Central](releases/1.5.1-central-publication.

## Unreleased

No changes yet.

## 1.6.0 — release preparation

Publication is pending; see the [release record](releases/1.6.0.md).

- Reduce unnecessary script-letter escaping in `forJavaScript` and
`forJavaScriptBlock` (#243). Interior letters remain readable; the input's last
character is escaped if it is C, I, P, R, S, or T (either case). Existing punctuation escapes and
Expand Down
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ has no runtime dependencies; optional JSP and Jakarta adapters provide view-laye
bindings. Encoding is one part of [XSS prevention][xss], alongside
safe templates, URL validation and other application controls.

**1.5.1 is available from Maven Central.** This patch release clarifies the
JavaScript and JSON documentation and strengthens parser regression tests.
Encoder behavior, public APIs, and runtime dependencies are unchanged from 1.5.0.
See the [release notes](releases/1.5.1.md) and
[publication verification](releases/1.5.1-central-publication.md).
**1.6.0 release preparation:** this minor release reduces unnecessary JavaScript
letter escaping while preserving recognized HTML-token protection across trusted
fragments. Encoded bytes and streaming behavior change; see the
[release notes](releases/1.6.0.md) for migration and verification.
Publication is not complete; the dependency example below targets the prepared
release. The latest verified Central release remains
[1.5.1](releases/1.5.1-central-publication.md) until publication is confirmed.

The parser-boundary security fixes introduced in 1.5.0 remain in effect;
versions through 1.4.1 do not contain those fixes. See
Expand All @@ -35,7 +37,7 @@ The three supported artifacts use group ID `org.owasp.encoder`:
<dependency>
<groupId>org.owasp.encoder</groupId>
<artifactId>encoder</artifactId>
<version>1.5.1</version>
<version>1.6.0</version>
</dependency>
```

Expand All @@ -46,9 +48,9 @@ on the same classpath or module path. See the [runtime matrix](compatibility/REA
[dependency/license inventory](docs/dependencies.md).

`encoder-esapi` was retired after 1.4.1 and is not included or supported in
1.5.x. Applications using it must [migrate away from the adapter](docs/encoder-esapi-retirement.md).
1.5.x or 1.6.0. Applications using it must [migrate away from the adapter](docs/encoder-esapi-retirement.md).

Published 1.5.1 API documentation: [core](https://javadoc.io/doc/org.owasp.encoder/encoder/1.5.1/),
Published 1.5.1 API documentation (1.6.0 indexing follows publication): [core](https://javadoc.io/doc/org.owasp.encoder/encoder/1.5.1/),
[javax JSP](https://javadoc.io/doc/org.owasp.encoder/encoder-jsp/1.5.1/) and
[Jakarta JSP](https://javadoc.io/doc/org.owasp.encoder/encoder-jakarta-jsp/1.5.1/).

Expand Down Expand Up @@ -175,4 +177,4 @@ links distinguish maintainer support from OWASP Foundation donations.
[xss]: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
[java-libraries]: https://devguide.owasp.org/en/05-implementation/03-secure-libraries/04-java-secure-libs/
[project]: https://owasp.org/projects/java-encoder
[release]: https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.5.1
[release]: https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.6.0
5 changes: 5 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Supported Versions

Version **1.6.0** is being prepared as an output-encoding refinement. It preserves
recognized HTML-token protection from 1.5.0 and introduces no new encoder
security fix. Until [publication is verified](releases/1.6.0.md), 1.5.1 remains
the current supported release shown below.

Version **1.5.1**, published **2026-10-15 UTC**, is the current supported
release. This documentation and build-maintenance patch preserves the 1.5.0
security fixes and introduces no new encoder security fix. The
Expand Down
13 changes: 7 additions & 6 deletions VERIFYING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ identity authority. Obtain [KEYS](KEYS) from a trusted project revision and chec
the fingerprint before use. Never import private key material to verify a release.

For 1.4.1 and later releases until a documented rotation, the expected project key
is `1C5F632B86809F2F5DB25092BEA0075F94074A9B`. The [1.5.1 publication verification](releases/1.5.1-central-publication.md)
records the signed tag, exact bundle, and comparison of Central and GitHub
downloads against the retained signed artifacts.
is `1C5F632B86809F2F5DB25092BEA0075F94074A9B`. The [1.6.0 release record](releases/1.6.0.md#verification-and-evidence)
tracks signing and publication of the prepared release. Do not treat a prepared
release as available. The [1.5.1 publication verification](releases/1.5.1-central-publication.md)
records the previous verified artifacts and signatures.

## Fresh public-only keyring

Download the artifact, its original `.asc`, and the trusted `KEYS`. This example
targets the published 1.5.1 release. For historical releases, use the full
targets 1.6.0 once its publication is verified. For historical releases, use the full
fingerprint mapped below and review the historical key's expiry and algorithms.
Commands use GnuPG and `shasum` (or equivalent SHA tools).

Expand All @@ -22,7 +23,7 @@ verify_home=$(mktemp -d)
chmod 700 "$verify_home"
gpg --homedir "$verify_home" --batch --no-autostart --import KEYS
expected_fingerprint=1C5F632B86809F2F5DB25092BEA0075F94074A9B
artifact=encoder-1.5.1.jar
artifact=encoder-1.6.0.jar
gpg --homedir "$verify_home" --no-autostart --fingerprint "$expected_fingerprint"
gpg --homedir "$verify_home" --batch --no-autostart --status-fd 1 \
--verify "$artifact.asc" "$artifact" > signature.status || exit 1
Expand All @@ -45,7 +46,7 @@ A Maven `.sha256` sidecar usually contains **only a hex digest**, not a filename
After fetching it over the intended distribution channel, form a check manifest:

```sh
artifact=encoder-1.5.1.jar
artifact=encoder-1.6.0.jar
expected_hash=$(tr -d '[:space:]' < "$artifact.sha256")
printf '%s\n' "$expected_hash" | grep -Eq '^[[:xdigit:]]{64}$' || exit 1
printf '%s %s\n' "$expected_hash" "$artifact" | shasum -a 256 --check || exit 1
Expand Down
2 changes: 1 addition & 1 deletion compatibility/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ fail these guards.
During ordinary `./mvnw verify`, Animal Sniffer checks each library against the Java 8
API signature. This catches linkage such as Java 9's covariant `CharBuffer.flip()`
even when bytecode still has class version 52. japicmp checks public/protected API
binary and source compatibility against **1.5.1** during **1.5.2-SNAPSHOT** development. The baseline guard selects the latest preceding semantic release tag,
binary and source compatibility against **1.5.1** for the prepared **1.6.0** release. The baseline guard selects the latest preceding semantic release tag,
including signed source commits integrated by squash merge; fetch all release tags
before running it. The old support classpath matches the 1.5.1 POMs (JSP 2.3.3,
Jakarta Servlet 6.1.0 and EL 6.0.1). Independent minimum-consumer fixtures remain
Expand Down
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<parent>
<groupId>org.owasp.encoder</groupId>
<artifactId>encoder-parent</artifactId>
<version>1.5.2-SNAPSHOT</version>
<version>1.6.0</version>
</parent>

<artifactId>encoder</artifactId>
Expand Down
11 changes: 5 additions & 6 deletions docs/compatibility-decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,13 @@ the CDATA maximum is 13×. Large CDATA values should use a Writer facade or
`EncodedWriter`; String facades retain the complete result but grow according to
actual output rather than reserving the maximum bound.

## Unreleased JavaScript output refinement (#243)
## JavaScript output refinement in 1.6.0 (#243)

Release recommendation: use a minor release (1.6.0), rather than assuming this
is patch-compatible. The evaluated values and supported HTML tokenizer protection
This change is prepared for the minor release 1.6.0, rather than a patch release. The evaluated values and supported HTML tokenizer protection
remain intact, but encoded bytes, explicit-flush spelling, and the previous literal
substring prohibition change. This proposal records the migration and parser
validation requirements; the current development snapshot version is not release
authorization. Existing published artifacts remain unchanged.
substring prohibition change. This record describes the migration and parser
validation requirements; release preparation does not establish publication.
See the [release record](../releases/1.6.0.md) for status. Existing published artifacts remain unchanged.

The script-fragment protection remains, with less escaping of ordinary letters.
HTML punctuation and whitespace still use the 1.5 escapes. Of the letters in
Expand Down
9 changes: 4 additions & 5 deletions docs/contexts.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Output contexts and boundaries

This guide describes the current development version, including the unreleased
JavaScript refinement for #243. Published 1.5.0 and 1.5.1 retain their broader
letter escapes; 1.5.1 clarified the 1.5.0 behavior without changing it. See the
[1.5.1 release record](../releases/1.5.1.md) for publication status.
This guide describes the prepared **1.6.0** release, including the JavaScript
refinement for #243. Published 1.5.0 and 1.5.1 retain their broader letter escapes.
See the [1.6.0 release record](../releases/1.6.0.md) for publication status.
The [Encode Javadoc source](../core/src/main/java/org/owasp/encoder/Encode.java) is
the detailed per-method contract; each method has a String-returning and a
`(Writer out, String input)` overload. `Encoders` exposes shared stateless encoders;
Expand Down Expand Up @@ -83,7 +82,7 @@ The general and block encoders prevent a nonempty encoded value from completing
recognized `</script` or `<script` tokens (case-insensitive, followed by an HTML
name delimiter), `<!--`, or `-->` with adjacent trusted literal text. They escape
space, `!`, hyphen (`\x2d`), `<`, `>`, slash, and relevant controls throughout
the input. In the unreleased refinement for #243, letters from `script` (either case) are escaped
the input. In 1.6.0, letters from `script` (either case) are escaped
only when they are the final input character. Interior letters remain readable;
a longer name such as `</scripture>` is not a script end tag. This preserves
HTML tokenizer containment while allowing harmless raw `</script` substrings
Expand Down
12 changes: 6 additions & 6 deletions docs/usage.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Java and JSP examples

These examples describe the current development version, including the
**unreleased** JavaScript refinement for #243. Published **1.5.1** retains
1.5.0's broader letter escaping; see the [release record](../releases/1.5.1.md).
These examples target the prepared **1.6.0** release, including the JavaScript
refinement for #243. See the [release record](../releases/1.6.0.md) for publication
status. Published 1.5.1 retains 1.5.0's broader letter escaping.
Features marked **1.5** were introduced in 1.5.0.

## HTML and Writer output
Expand Down Expand Up @@ -62,8 +62,8 @@ result into an HTML-parsing API introduces another context to secure.

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. In the
unreleased refinement for #243, only a final `C`, `I`, `P`, `R`, `S`, or `T` (either case) receives that
letters in `script`) while preserving the JavaScript string value. In
1.6.0, only a final `C`, `I`, `P`, `R`, `S`, or `T` (either case) receives that
letter escape; interior letters remain readable. For example, `script` becomes
`scrip\x74` and `http://google.com` becomes `http:\/\/google.com`.
The punctuation and terminal-letter escapes together prevent recognized HTML
Expand Down Expand Up @@ -159,7 +159,7 @@ and the [packaged JSP engine checks](../compatibility/jsp-engine/README.md).
## Java modules

The explicit module name for core is `owasp.encoder`. After verifying and obtaining
`encoder-1.5.1.jar`, put that unchanged JAR in `lib/`, then create:
`encoder-1.6.0.jar`, put that unchanged JAR in `lib/`, then create:

`src/example.app/module-info.java`:

Expand Down
2 changes: 1 addition & 1 deletion jakarta-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<jackson.build.version>3.1.7</jackson.build.version>
<!-- Must equal the version in the root pom.xml so this app tests the
encoder-jakarta-jsp built in the same reactor. CI checks this. -->
<encoder.version>1.5.2-SNAPSHOT</encoder.version>
<encoder.version>1.6.0</encoder.version>
</properties>
<dependencies>
<dependency>
Expand Down
2 changes: 1 addition & 1 deletion jakarta/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<parent>
<groupId>org.owasp.encoder</groupId>
<artifactId>encoder-parent</artifactId>
<version>1.5.2-SNAPSHOT</version>
<version>1.6.0</version>
</parent>

<artifactId>encoder-jakarta-jsp</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion jsp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<parent>
<groupId>org.owasp.encoder</groupId>
<artifactId>encoder-parent</artifactId>
<version>1.5.2-SNAPSHOT</version>
<version>1.6.0</version>
</parent>

<artifactId>encoder-jsp</artifactId>
Expand Down
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

<groupId>org.owasp.encoder</groupId>
<artifactId>encoder-parent</artifactId>
<version>1.5.2-SNAPSHOT</version>
<version>1.6.0</version>
<packaging>pom</packaging>

<name>OWASP Java Encoder Project</name>
Expand Down Expand Up @@ -78,7 +78,7 @@
<developerConnection>scm:git:git@github.com:OWASP/owasp-java-encoder.git</developerConnection>
<connection>scm:git:https://github.com/OWASP/owasp-java-encoder.git</connection>
<url>https://github.com/OWASP/owasp-java-encoder</url>
<tag>HEAD</tag>
<tag>v1.6.0</tag>
</scm>

<issueManagement>
Expand Down Expand Up @@ -115,7 +115,7 @@

<properties>
<!-- Reviewed release-source timestamp; never build wall-clock time. -->
<project.build.outputTimestamp>2026-10-15T16:37:02Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2026-10-18T17:27:13Z</project.build.outputTimestamp>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Most recent immutable release strictly older than this project version;
Expand Down
106 changes: 106 additions & 0 deletions releases/1.6.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# OWASP Java Encoder 1.6.0

**Release preparation; not yet published.** The latest verified Central release
remains [1.5.1](1.5.1-central-publication.md). This minor release reduces
unnecessary JavaScript letter escaping while preserving recognized HTML-token
protection across trusted fragments. It introduces no new encoder security fix.
Do not treat a successful build or staging validation as publication.

## Highlights and compatibility

[PR #247](https://github.com/OWASP/owasp-java-encoder/pull/247) resolves
[#243](https://github.com/OWASP/owasp-java-encoder/issues/243):

- `forJavaScript` and `forJavaScriptBlock` leave interior script-name letters
readable. The last input character remains escaped if it is C, I, P, R, S,
or T in either case. Punctuation and whitespace escapes remain.
- HTML does not remove whitespace inside tag names. Escaping `<` in a complete
string addresses the HTML tag delimiter concern, but cannot protect fragments
whose trusted prefix supplies `<`. The retained terminal escape protects that
supported composition case.
- `EncodedWriter.flush()` safely emits a pending script letter or high surrogate
in general/block JavaScript modes. Flush before writing directly to its wrapped
writer; prefer the complete-value Writer facade for a value followed by trusted
output. Ordinary chunking matches whole-value output. Flushes can add escapes
while preserving the JavaScript UTF-16 value.

| Input | 1.5.1 general/block output | 1.6.0 general/block output |
| --- | --- | --- |
| `http://google.com` | `h\x74\x74\x70:\/\/google.\x63om` | `http:\/\/google.com` |
| `script` | `\x73\x63\x72\x69\x70\x74` | `scrip\x74` |
| `i` | `\x69` | `\x69` |
| `cat` | `\x63a\x74` | `ca\x74` |

The final-letter rule is conservative, not minimal: `csript` becomes
`csrip\x74` even though it is not a script tag name. Source and attribute-only
modes are unchanged. The guarantee concerns recognized HTML tokens, rather than
every literal `</script` substring; longer names such as `</scripture>` are
harmless to the HTML script tokenizer. Existing context and insertion-boundary
requirements still apply, including empty-input and unsafe-template exclusions.

Encoded bytes, snapshots, signatures and cache keys can change. Low-level
`Encoder.encode` callers must preserve unread input after UNDERFLOW and supply
more input or mark end-of-input, now including a retained ASCII letter.
See the [migration record](../docs/compatibility-decisions.md#javascript-output-refinement-in-160-243).

Java 8 remains the minimum runtime. Public APIs, null handling, JavaScript string
values, runtime dependencies, Maven identities, module/bundle identities and
servlet namespaces are unchanged. Core has no runtime dependencies. Keep core
and adapter versions aligned; do not combine javax and Jakarta adapters on one
classpath or module path.

The [1.5.0 security fixes](1.5.0.md) remain in effect. Applications on older
versions should follow that release's migration guidance and
[security advisory](https://github.com/OWASP/owasp-java-encoder/security/advisories/GHSA-g8p6-7r8f-qrpv).

## Coordinates and availability

Prepared group `org.owasp.encoder`, version `1.6.0`: `encoder`, `encoder-jsp`,
`encoder-jakarta-jsp`, and parent `encoder-parent`. The optional test WAR is not
published. `encoder-esapi` remains retired after 1.4.1 and is not included.
No 1.6.0 Central availability is claimed until exact artifacts are verified.

## Verification and evidence

The reference toolchain is Eclipse Temurin **17.0.20.1+1**, committed Maven
**3.10.0**, and macOS arm64 with the UTC locale/timezone settings in
[RELEASING.md](../RELEASING.md). The reviewed source timestamp is
`2026-10-18T17:27:13Z`.

The project signing identity is **OWASP Java Encoder Release**, full primary
fingerprint `1C5F632B86809F2F5DB25092BEA0075F94074A9B`. Verify original detached
signatures and signed checksum manifests using [KEYS](../KEYS) and
[VERIFYING.md](../VERIFYING.md). Release acceptance requires the exact committed
sources, clean-cache builds, packaged consumers, Docker/browser/WAR tests,
reproducible unsigned payload comparison, all required CI/security checks,
signature verification and comparison of published bytes with retained artifacts.
Those release-specific results and the final source/tag/bundle identities must
be recorded before publication is described as verified.

## Backlog and review disposition

The complete open-issue/PR inventory was empty on **2026-10-18 at 17:27 UTC**,
after #247 merged as `300ef20c1bfff8c3d4c68216d68f3fe742b0a559` and #243 closed.
Repeat the inventory immediately before publication.

Model-assisted review followed [MODELS.md](../MODELS.md). Astra coordinated
resolution; Sol 6.1, Opus 5.5, Mythos 5.1 and Sonnet 5.5 recommended merging
the final implementation/documentation revision
`da8b7a0d298c952aee9064f67dec75e0ab16a32f`. Claude Code 2.1.302 response metadata
confirmed `claude-opus-5-5`, `claude-mythos-5-1`, and `claude-sonnet-5-5`.
Codex agent slots requested `gpt-6-astra` and `gpt-6.1-sol`; the agent interface
did not independently attest their runtime identities. Daybreak eligibility was
unavailable, so no Daybreak review is claimed. AI review is not independent
maintainer approval. Jim Manico explicitly authorized the existing audit-visible
PR-only review bypass for #247; all required CI/security gates passed.

On that revision, the local clean reactor, 36 repository tests, 17 compatibility
tests and Java 17 packaged consumers passed. The unchanged implementation passed
12 Chrome tests, and 36 focused Chrome 155 cases checked the latest issue comment.
Final CI included packaged Java 8/11/17/21/25 consumers, Java 8 tests and the
Docker/browser/WAR fixture. These results do not replace the release-commit gates.

A nonblocking streaming cost remains: a long run of script letters after a pending
letter takes the leftover-buffer path repeatedly. One local 1 MiB probe measured
about 4.3 times the direct-write time, with linear work and bounded buffer memory.
No general performance improvement or cross-browser equivalence is claimed.
Loading