From 9c0e43e40d79d3fe65f13253138ebf266e7b0784 Mon Sep 17 00:00:00 2001 From: Jim Manico Date: Mon, 28 Sep 2026 14:03:49 -0700 Subject: [PATCH 1/2] Complete 1.5.0 publication follow-up and resume development --- .github/CI_SECURITY.md | 4 +- .github/DEPENDENCY_DECISIONS.md | 11 +++- CHANGELOG.md | 8 ++- README.md | 16 ++--- RELEASING.md | 22 ++++--- SECURITY.md | 13 +++-- VERIFYING.md | 10 ++-- compatibility/README.md | 10 +++- core/pom.xml | 2 +- docs/contexts.md | 5 +- docs/dependencies.md | 5 +- docs/usage.md | 7 +-- jakarta-test/pom.xml | 2 +- jakarta/pom.xml | 6 +- jsp/pom.xml | 4 +- pom.xml | 11 ++-- releases/1.5.0-central-publication.md | 77 +++++++++++++++++++++++++ releases/1.5.0.md | 27 ++++----- scripts/tests/test_ci_policy.py | 6 +- scripts/tests/test_release_baselines.py | 50 +++++++++++++++- 20 files changed, 219 insertions(+), 77 deletions(-) create mode 100644 releases/1.5.0-central-publication.md diff --git a/.github/CI_SECURITY.md b/.github/CI_SECURITY.md index 67cc6c0..9e51925 100644 --- a/.github/CI_SECURITY.md +++ b/.github/CI_SECURITY.md @@ -67,10 +67,10 @@ for child or fixture POMs. Graph reports and submission JSON are retained for inspection. Inspect representative Jakarta Spring/Tomcat dependencies in the resulting graph; alert counts are not gates. -The immutable 1.4.1 Java Encoder artifacts used by japicmp are intentional +The immutable 1.5.0 Java Encoder artifacts used by japicmp are intentional development-only comparison inputs. Keep them visible in the build graph: an alert on a baseline artifact describes that historical input, not a dependency shipped -to 1.5 consumers, and must be assessed rather than hidden with a graph filter. +to current development consumers, and must be assessed rather than hidden with a graph filter. All submissions use detector `encoder-maven-build-graph` with distinct, stable correlators. Keep the action's detector inputs synchronized with the diff --git a/.github/DEPENDENCY_DECISIONS.md b/.github/DEPENDENCY_DECISIONS.md index 9320684..7b3dce8 100644 --- a/.github/DEPENDENCY_DECISIONS.md +++ b/.github/DEPENDENCY_DECISIONS.md @@ -25,7 +25,7 @@ old **OSGi framework** compatibility fixture. Use `javax.servlet.jsp-api` **2.3.3** as the published `encoder-jsp` provided dependency. Keep JSP 2.2.1, Servlet 3.0.1 and EL 2.2.5 as the independent minimum -consumer fixture. Japicmp resolves 1.4.1 against the old support API and the 1.5 +consumer fixture. For the 1.5.0 release, japicmp resolved 1.4.1 against the old support API and the 1.5 artifact against the new one, so inherited API changes are not hidden. The Java 8, JPMS, OSGi and packaged Jasper checks continue to exercise the original artifacts. This is a consumer-POM dependency change, not a claim that the minimum supported @@ -36,8 +36,13 @@ classpath. Their test-scope declarations remain visible in the published source POM, but Maven does not propagate them into ordinary consumer dependency graphs and their classes do not enter the adapter JAR. Keep the independent Java 8 packaged-consumer fixture on Jakarta Pages 3.0.0, Servlet 5.0.0 and EL 4.0.0. The -old Servlet 6.0.0 and EL 4.0.0 support JARs remain explicit japicmp inputs for the -1.4.1 side of the comparison; the new side uses the new test APIs. +old Servlet 6.0.0 and EL 4.0.0 support JARs were explicit japicmp inputs for the +1.4.1 side of the release comparison; the new side used the new test APIs. + +After publication, `1.5.1-SNAPSHOT` compares against the immutable 1.5.0 artifacts. +Its old support classpaths therefore use JSP 2.3.3, Jakarta Servlet 6.1.0 and +EL 6.0.1, matching that release. This does not change the independent minimum +consumer fixtures or the published provided dependencies. ## Deferred proposals and reconsideration conditions diff --git a/CHANGELOG.md b/CHANGELOG.md index 9693ae4..59ad786 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,15 @@ Released entries are grounded in the linked immutable tags, GitHub release notes and retained README announcements. Dates below are GitHub publication dates in UTC where a release record exists; older announcement/tag dates are labeled. An open proposal is not a release. Historical tags, assets and signatures remain -unchanged. [1.4.1 is also available from Central](releases/1.4.1-central-publication.md). +unchanged. [1.5.0 is available from Central](releases/1.5.0-central-publication.md). ## Unreleased -No changes are recorded after 1.5.0 yet. +- Resume development at `1.5.1-SNAPSHOT`, with the immutable 1.5.0 public-API + baseline and its matching support APIs. Minimum-consumer fixtures are unchanged. +- Discover release tags independently of commit ancestry so squash merges cannot + leave the compatibility baseline stale; add isolated Git regressions. +- Record verified 1.5.0 publication and replace pending-availability notices. ## 1.5.0 — 2026-09-28 UTC diff --git a/README.md b/README.md index bc674bd..513619f 100644 --- a/README.md +++ b/README.md @@ -9,16 +9,17 @@ 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. -**Release preparation:** version 1.5.0 fixes parser-boundary vulnerabilities in +**Released 2026-09-28:** version 1.5.0 fixes parser-boundary vulnerabilities in JavaScript-in-HTML, CDATA, and XML-comment fragment composition. Versions through -1.4.1 do not contain those fixes. The signed 1.5.0 artifacts are not available -until the maintainers complete the release gates and update this notice with the -verified GitHub and Maven Central links. See the [1.5.0 release notes](releases/1.5.0.md) +1.4.1 do not contain those fixes. The [signed GitHub release][release] and +[Maven Central artifacts](releases/1.5.0-central-publication.md) have been +independently verified. See the [1.5.0 release notes](releases/1.5.0.md), +[security advisory](https://github.com/OWASP/owasp-java-encoder/security/advisories/GHSA-g8p6-7r8f-qrpv) and [VERIFYING.md](VERIFYING.md). ## Start using the OWASP Java Encoders -After 1.5.0 publication is independently verified, select the dependency you need. +Select the dependency you need. The three supported artifacts use group ID `org.owasp.encoder`: | Artifact ID | Purpose and runtime dependencies | @@ -39,10 +40,9 @@ Replace `encoder` with one tag adapter artifact ID when needed; each adapter bri in core. Keep separately managed core/adapter versions aligned. Use **one** of the javax or Jakarta taglib JARs: they share `org.owasp.encoder.tag` and must not coexist on the same classpath or module path. See the [runtime matrix](compatibility/README.md) and -[dependency/license inventory](docs/dependencies.md). Do not use the example version -until its signed artifacts and Central availability have been verified. +[dependency/license inventory](docs/dependencies.md). -`encoder-esapi` was retired after 1.4.1 and will not be published or supported in +`encoder-esapi` was retired after 1.4.1 and is not included or supported in 1.5.0. Applications using it must [migrate away from the adapter](docs/encoder-esapi-retirement.md). ```java diff --git a/RELEASING.md b/RELEASING.md index b93f0dd..835487f 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,23 +1,23 @@ # Releasing OWASP Java Encoder -## Release gate for 1.5 +## Release gate -Do not tag, publish, or announce a 1.5 release until **all open issues and all +Do not tag, publish, or announce a release until **all open issues and all open pull requests have been handled**. Before considering release approval, inventory the full open backlog and record the outcome and supporting review or verification for every item. Completing a maintenance batch does not satisfy -this gate on its own. Keep 1.5 development at `1.5.0-SNAPSHOT` until maintainers +this gate on its own. Keep current development at `1.5.1-SNAPSHOT` until maintainers deliberately create the exact release commit after the technical gates pass. -Changing that commit to `1.5.0` is release preparation, not release approval. +Changing that commit to a release version is release preparation, not release approval. The [2026-09-26 maintenance closeout](releases/maintenance-closeout.md) records the final backlog inventory and dispositions for #110 and #169. A closed tracker -does not waive this gate: repeat the complete open-issue/PR inventory when a 1.5 +does not waive this gate: repeat the complete open-issue/PR inventory when a new release is actually proposed and obtain release approval then. -The signed 1.4.1 release has been [published to Central and verified](releases/1.4.1-central-publication.md). -That publication is separate from the 1.5 release gate. Do not rebuild or replace -1.4.1 artifacts, republish its coordinates, or move its tag. +The signed 1.5.0 release has been [published to Central and verified](releases/1.5.0-central-publication.md). +Repeat these gates for each subsequent release. Do not rebuild or replace +published artifacts, republish existing coordinates, or move release tags. ## Publishing access and project identity @@ -158,7 +158,11 @@ uploading. Keep an audit record of the exact uploaded bundle and its SHA-256. that has not actually published. 5. Set main to the next unreleased version (for example `1.5.1-SNAPSHOT` or `1.6.0-SNAPSHOT`, chosen through version review), update `jakarta-test` - accordingly, and reset the SCM tag to `HEAD`. README examples and the + accordingly, and reset the SCM tag to `HEAD`. Advance `public.api.baseline.version` + and its old support-API classpaths to the newly published immutable release. + Fetch all release tags before running the baseline regression: the tested + release commit can be outside main's ancestry after a squash merge. + README examples and the supported-version table continue to refer to the published release. 6. Verify GitHub CI on main, update the OWASP project page, and check javadoc.io after its indexing delay. diff --git a/SECURITY.md b/SECURITY.md index 92fb8aa..83996ed 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,9 +2,11 @@ ## Supported Versions -Version **1.5.0** is the prepared security release. Do not treat it as available -until the signed GitHub artifacts and Maven Central publication have been -independently verified and this paragraph is updated with the exact links and date. +Version **1.5.0**, published **2026-09-28 UTC**, is the current security release. +The [signed GitHub assets](https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.5.0) +and [Maven Central publication](releases/1.5.0-central-publication.md) have been +independently verified. See [GHSA-g8p6-7r8f-qrpv](https://github.com/OWASP/owasp-java-encoder/security/advisories/GHSA-g8p6-7r8f-qrpv) +for affected versions and migration guidance. Only the latest 1.x release receives security fixes. Fixes ship in a new release; older release lines are not patched. @@ -85,11 +87,14 @@ release tag, then verify: ```sh gpg --import KEYS gpg --verify encoder-1.5.0.jar.asc encoder-1.5.0.jar +gpg --verify SHA256SUMS.asc SHA256SUMS +gpg --verify SHA512SUMS.asc SHA512SUMS shasum -a 256 -c SHA256SUMS shasum -a 512 -c SHA512SUMS ``` -The `SHA256SUMS` and `SHA512SUMS` manifests are included with the GitHub release +For full-fingerprint checks in a fresh public-only keyring, follow +[VERIFYING.md](VERIFYING.md). The `SHA256SUMS` and `SHA512SUMS` manifests are included with the GitHub release assets. Maven Central provides individual checksum files alongside each artifact. A new project key and its fingerprint must be added to `KEYS` before a release uses it. Previously published artifacts retain their original signatures. diff --git a/VERIFYING.md b/VERIFYING.md index 3a2a4f0..4594d53 100644 --- a/VERIFYING.md +++ b/VERIFYING.md @@ -6,14 +6,14 @@ 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.4.1 release instructions](releases/1.4.1.md#verification) -cover its signed GitHub assets. The [Central publication verification](releases/1.4.1-central-publication.md) +is `1C5F632B86809F2F5DB25092BEA0075F94074A9B`. The [1.5.0 release record](releases/1.5.0.md#verification-and-evidence) +covers its signed GitHub assets. The [Central publication verification](releases/1.5.0-central-publication.md) confirms that Central serves the same artifacts and signatures. ## Fresh public-only keyring Download the artifact, its original `.asc`, and the trusted `KEYS`. This example -verifies the published 1.4.1 release. For historical releases, use the full +verifies the published 1.5.0 release. 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). @@ -22,7 +22,7 @@ verify_home=$(mktemp -d) chmod 700 "$verify_home" gpg --homedir "$verify_home" --batch --no-autostart --import KEYS expected_fingerprint=1C5F632B86809F2F5DB25092BEA0075F94074A9B -artifact=encoder-1.4.1.jar +artifact=encoder-1.5.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 @@ -45,7 +45,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.4.1.jar +artifact=encoder-1.5.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 diff --git a/compatibility/README.md b/compatibility/README.md index 485c57f..f8c3679 100644 --- a/compatibility/README.md +++ b/compatibility/README.md @@ -84,8 +84,12 @@ 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.4.1**, the immutable release immediately -preceding 1.5.0. Update the pinned baseline for the next development version. Missing +binary and source compatibility against **1.5.0** during **1.5.1-SNAPSHOT** +development. 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.0 POMs (JSP 2.3.3, +Jakarta Servlet 6.1.0 and EL 6.0.1). Independent minimum-consumer fixtures remain +unchanged. Update these pins together after each release. Missing types are not broadly ignored: dependencies are resolved so inherited API changes remain visible. Both checks run in existing `build.yaml` jobs because those jobs reach the `verify` phase. @@ -135,7 +139,7 @@ multi-release layout remain unchanged. ## Published identities and development import ranges -The tables below describe the prepared **1.5.0** artifacts. The names are +The tables below describe the published **1.5.0** artifacts. The names are historical identities preserved in 1.x; the OSGi import floors reflect the new 1.5 calls and must not be projected onto older published JARs. diff --git a/core/pom.xml b/core/pom.xml index a7df0d7..9c24dbe 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -42,7 +42,7 @@ org.owasp.encoder encoder-parent - 1.5.0 + 1.5.1-SNAPSHOT encoder diff --git a/docs/contexts.md b/docs/contexts.md index fd2346e..7555da5 100644 --- a/docs/contexts.md +++ b/docs/contexts.md @@ -1,8 +1,7 @@ # Output contexts and boundaries -This guide describes version **1.5.0**; feature introductions are marked below. -Do not treat that version as available until the [release-preparation notice](../README.md) -is updated with independently verified signed artifacts and Maven Central links. +This guide describes the published version **1.5.0**; feature introductions are +marked below. See the [verified downloads](../releases/1.5.0-central-publication.md). 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; diff --git a/docs/dependencies.md b/docs/dependencies.md index 4e9bad4..b6a0e3b 100644 --- a/docs/dependencies.md +++ b/docs/dependencies.md @@ -17,8 +17,9 @@ unsupported; see the [retirement and migration notice](encoder-esapi-retirement. ## Consumer dependency inventory — 2026-09-27 Generated from dependency-plugin 3.11.0's resolved reactor `dependency:tree` -JSON for the reviewed `1.5.0-SNAPSHOT` candidate. Release preparation does not -change the published dependency graph. This inventory includes the publishable +JSON for the reviewed `1.5.0-SNAPSHOT` candidate. The published 1.5.0 POMs retain +this consumer graph; see the [publication record](../releases/1.5.0-central-publication.md). +This inventory includes the publishable modules' compile/runtime and provided scopes, excludes test/plugin dependencies and this project's own BSD-3-Clause modules, and identifies the consuming module. diff --git a/docs/usage.md b/docs/usage.md index 30a36ae..7a37227 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,9 +1,8 @@ # Java and JSP examples -These examples target version **1.5.0**. Do not use that coordinate until the -[release-preparation notice](../README.md) is updated with independently verified -signed artifacts and Maven Central links. Features marked **1.5** are new in this -release. +These examples target the published version **1.5.0**. See the +[verified downloads](../releases/1.5.0-central-publication.md). +Features marked **1.5** are new in this release. ## HTML and Writer output diff --git a/jakarta-test/pom.xml b/jakarta-test/pom.xml index 2c0f5ed..b8facab 100644 --- a/jakarta-test/pom.xml +++ b/jakarta-test/pom.xml @@ -28,7 +28,7 @@ 4.49.0 - 1.5.0 + 1.5.1-SNAPSHOT diff --git a/jakarta/pom.xml b/jakarta/pom.xml index ce346b8..bedd65e 100644 --- a/jakarta/pom.xml +++ b/jakarta/pom.xml @@ -42,7 +42,7 @@ org.owasp.encoder encoder-parent - 1.5.0 + 1.5.1-SNAPSHOT encoder-jakarta-jsp @@ -61,9 +61,9 @@ 1.000 org.owasp.encoder.jakarta org.owasp.encoder.jakarta-jsp - 4.0.0 + 6.0.1 6.0.1 - 6.0.0 + 6.1.0 6.1.0 ${settings.localRepository}/org/owasp/encoder/encoder/${public.api.baseline.version}/encoder-${public.api.baseline.version}.jar${path.separator}${settings.localRepository}/jakarta/servlet/jsp/jakarta.servlet.jsp-api/3.0.0/jakarta.servlet.jsp-api-3.0.0.jar${path.separator}${settings.localRepository}/jakarta/el/jakarta.el-api/${jakarta.el.api.baseline.version}/jakarta.el-api-${jakarta.el.api.baseline.version}.jar${path.separator}${settings.localRepository}/jakarta/servlet/jakarta.servlet-api/${jakarta.servlet.api.baseline.version}/jakarta.servlet-api-${jakarta.servlet.api.baseline.version}.jar ${maven.multiModuleProjectDirectory}/core/target/encoder-${project.version}.jar${path.separator}${settings.localRepository}/jakarta/servlet/jsp/jakarta.servlet.jsp-api/3.0.0/jakarta.servlet.jsp-api-3.0.0.jar${path.separator}${settings.localRepository}/jakarta/el/jakarta.el-api/${jakarta.el.api.version}/jakarta.el-api-${jakarta.el.api.version}.jar${path.separator}${settings.localRepository}/jakarta/servlet/jakarta.servlet-api/${jakarta.servlet.api.version}/jakarta.servlet-api-${jakarta.servlet.api.version}.jar diff --git a/jsp/pom.xml b/jsp/pom.xml index ee3829c..edc8919 100644 --- a/jsp/pom.xml +++ b/jsp/pom.xml @@ -42,7 +42,7 @@ org.owasp.encoder encoder-parent - 1.5.0 + 1.5.1-SNAPSHOT encoder-jsp @@ -61,7 +61,7 @@ 1.000 org.owasp.encoder.jsp org.owasp.encoder.jsp - 2.2.1 + 2.3.3 2.3.3 ${settings.localRepository}/org/owasp/encoder/encoder/${public.api.baseline.version}/encoder-${public.api.baseline.version}.jar${path.separator}${settings.localRepository}/javax/servlet/jsp/javax.servlet.jsp-api/${jsp.api.baseline.version}/javax.servlet.jsp-api-${jsp.api.baseline.version}.jar${path.separator}${settings.localRepository}/javax/el/javax.el-api/2.2.5/javax.el-api-2.2.5.jar${path.separator}${settings.localRepository}/javax/servlet/javax.servlet-api/3.0.1/javax.servlet-api-3.0.1.jar ${maven.multiModuleProjectDirectory}/core/target/encoder-${project.version}.jar${path.separator}${settings.localRepository}/javax/servlet/jsp/javax.servlet.jsp-api/${jsp.api.version}/javax.servlet.jsp-api-${jsp.api.version}.jar${path.separator}${settings.localRepository}/javax/el/javax.el-api/2.2.5/javax.el-api-2.2.5.jar${path.separator}${settings.localRepository}/javax/servlet/javax.servlet-api/3.0.1/javax.servlet-api-3.0.1.jar diff --git a/pom.xml b/pom.xml index 73c485d..72659fb 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ org.owasp.encoder encoder-parent - 1.5.0 + 1.5.1-SNAPSHOT pom OWASP Java Encoder Project @@ -78,7 +78,7 @@ scm:git:git@github.com:OWASP/owasp-java-encoder.git scm:git:https://github.com/OWASP/owasp-java-encoder.git https://github.com/OWASP/owasp-java-encoder - v1.5.0 + HEAD @@ -114,13 +114,14 @@ - + 2026-09-28T13:21:37Z UTF-8 UTF-8 - 1.4.1 + scripts/tests/test_release_baselines.py checks all local release tags, + including release commits integrated by squash merge. --> + 1.5.0 ${settings.localRepository}/org/owasp/encoder/${project.artifactId}/${public.api.baseline.version}/${project.artifactId}-${public.api.baseline.version}.jar ${project.build.directory}/${project.build.finalName}.jar diff --git a/releases/1.5.0-central-publication.md b/releases/1.5.0-central-publication.md new file mode 100644 index 0000000..77127d2 --- /dev/null +++ b/releases/1.5.0-central-publication.md @@ -0,0 +1,77 @@ +# OWASP Java Encoder 1.5.0 publication + +Published **2026-09-28 UTC**. Jim Manico uploaded the retained signed bundle and +confirmed Central Portal status **Published** for deployment +`b448a073-7b5a-4442-bbcc-e4e1ee8fa04c`. + +## Immutable release identities + +- Exact tested source: `3fbc5da5bcdc49a6e2b4f39d3df7410b7c13d07d`. +- Signed tag: `v1.5.0`; annotated object `a5628da0f1586f904e6702e544c84022a0425466`. +- Signing fingerprint: `1C5F632B86809F2F5DB25092BEA0075F94074A9B`. +- [Central bundle](https://github.com/OWASP/owasp-java-encoder/releases/download/v1.5.0/owasp-java-encoder-1.5.0-central-bundle.zip) + SHA-256: `107b0e4e1f459087d6bbd1e37222c05c7c4630fa55d52bc1e7c99c0077897590`. +- Source timestamp: `2026-09-28T13:21:37Z`. + +[PR #229](https://github.com/OWASP/owasp-java-encoder/pull/229) was squash-merged as +`030c137fc14f277afc5fbe303d2ca8a149f8068b`. That commit and the tagged tested source +have the identical tree `3b1c1acbc4a706175f7b8107f8c2a16503004b73`, but distinct +commit identities. The signed tag deliberately preserves the tested source. +Do not move it to the squash commit or rebuild/re-sign the published artifacts. + +## Download verification + +At **20:09:39 UTC**, all nine binary/source/Javadoc JARs, four POMs and thirteen +detached signatures were downloaded from public Maven Central. All **26 files +matched the retained signed files byte for byte**. All thirteen signatures +verified against the full expected project fingerprint in a fresh public-only +keyring. + +| Artifact | Published files | +| --- | --- | +| `encoder` | [1.5.0](https://repo.maven.apache.org/maven2/org/owasp/encoder/encoder/1.5.0/) | +| `encoder-jsp` | [1.5.0](https://repo.maven.apache.org/maven2/org/owasp/encoder/encoder-jsp/1.5.0/) | +| `encoder-jakarta-jsp` | [1.5.0](https://repo.maven.apache.org/maven2/org/owasp/encoder/encoder-jakarta-jsp/1.5.0/) | +| `encoder-parent` | [1.5.0](https://repo.maven.apache.org/maven2/org/owasp/encoder/encoder-parent/1.5.0/) | + +Neither the optional test WAR nor `encoder-esapi` is published in 1.5.0. + +All **32 uploaded GitHub assets** were downloaded and matched the retained files before +the [GitHub release](https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.5.0) +was published at **20:17:53 UTC**. Public asset digests were checked again afterward. +The assets include the exact bundle, thirteen payloads and their signatures, +public `KEYS`, and signed [SHA256SUMS](https://github.com/OWASP/owasp-java-encoder/releases/download/v1.5.0/SHA256SUMS) +and [SHA512SUMS](https://github.com/OWASP/owasp-java-encoder/releases/download/v1.5.0/SHA512SUMS). +Authenticate the manifests' detached signatures before checking their entries; +see [VERIFYING.md](../VERIFYING.md). + +The tag's cryptographic signature verified against the same project key. +GitHub's `unknown_key` account-association status is distinct from that successful +signature verification; the dedicated project key was not added to a personal +GitHub account merely to change the badge. + +[GHSA-g8p6-7r8f-qrpv](https://github.com/OWASP/owasp-java-encoder/security/advisories/GHSA-g8p6-7r8f-qrpv) +was published at **20:18:27 UTC**, after the fixed artifacts became available. +The three retained libraries are fixed in 1.5.0. The retired ESAPI adapter has no +fixed adapter release; follow its [migration guide](../docs/encoder-esapi-retirement.md). + +## Build and compatibility evidence + +The retained artifacts used Eclipse Temurin **17.0.20.1+1**, committed Maven +wrapper **3.9.16**, UTC and the recorded source timestamp. The clean local reactor +passed **2,287 tests**, with zero failures, errors or skips. All thirteen unsigned +payload files matched two fresh source-export builds. Public API compatibility +was checked against 1.4.1 for all three retained libraries. + +Post-merge [Java CI](https://github.com/OWASP/owasp-java-encoder/actions/runs/36471162477), +[packaged consumers](https://github.com/OWASP/owasp-java-encoder/actions/runs/36471162240) +and [CodeQL](https://github.com/OWASP/owasp-java-encoder/actions/runs/36471162191) +passed, including the browser and Java 8 gates. Packaged consumers passed on +Java 8, 11, 17, 21 and 25. The complete open-issue, pull-request and Dependabot +inventories were empty at **20:19:55 UTC**; no alert was dismissed. + +Publication is complete. Main resumes at `1.5.1-SNAPSHOT` with the immutable +1.5.0 compatibility baseline. Website updates and Javadoc indexing are separate +from verified artifact availability. Pre-publication notices in the immutable +source tag remain historical; this later record confirms publication without +altering those sources or their signatures. diff --git a/releases/1.5.0.md b/releases/1.5.0.md index b8412e5..4c155be 100644 --- a/releases/1.5.0.md +++ b/releases/1.5.0.md @@ -1,9 +1,9 @@ # OWASP Java Encoder 1.5.0 -**Publication status:** prepared for publication on 2026-09-28 UTC. The exact -release commit, signed GitHub assets, Maven Central URLs, and independent Central -verification are still pending. Do not treat a passing build, this file, or an -unsigned tag as an available release. +**Published 2026-09-28 UTC.** The [signed GitHub release](https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.5.0) +and [Maven Central artifacts](1.5.0-central-publication.md) were downloaded and +independently verified. The signed `v1.5.0` tag identifies exact tested source +`3fbc5da5bcdc49a6e2b4f39d3df7410b7c13d07d`. ## Highlights and security @@ -19,8 +19,7 @@ unsigned tag as an available release. This security release is tracked by [GHSA-g8p6-7r8f-qrpv](https://github.com/OWASP/owasp-java-encoder/security/advisories/GHSA-g8p6-7r8f-qrpv). -The advisory must remain private until fixed artifacts are available, then be -published before the public announcement. +The advisory was published after fixed artifacts became available. ## Compatibility and migration @@ -91,9 +90,9 @@ Group `org.owasp.encoder`, version `1.5.0`: - `encoder-jakarta-jsp` - parent `encoder-parent` -The optional `jakarta-test` WAR and `encoder-esapi` are not published. Add exact -Central and signed GitHub-release links only after those artifacts have been -downloaded and verified independently. +The optional `jakarta-test` WAR and `encoder-esapi` are not published. The +[publication record](1.5.0-central-publication.md) links every published coordinate +and the verified signed downloads. ## Verification and evidence @@ -118,9 +117,7 @@ The signing identity is expected to be the independently verified full primary fingerprint `1C5F632B86809F2F5DB25092BEA0075F94074A9B`; verify it again rather than trusting this text. -Before creating the release commit, replace the provisional -`project.build.outputTimestamp` with that commit's exact UTC timestamp. Then -record the exact release SHA in the external release evidence (and, if desired, -in a later documentation commit), create and verify the signed `v1.5.0` tag on -that SHA, assemble the signed bundle with `scripts/package-release.py`, and update -this status only after GitHub and Central publication checks succeed. +The release uses `project.build.outputTimestamp=2026-09-28T13:21:37Z`, the tested +source commit's exact UTC timestamp. The [publication record](1.5.0-central-publication.md) +records the signed tag, bundle hash, verification results and CI runs. This +post-publication documentation does not change the original tag or release bytes. diff --git a/scripts/tests/test_ci_policy.py b/scripts/tests/test_ci_policy.py index 5a19713..b056bf5 100644 --- a/scripts/tests/test_ci_policy.py +++ b/scripts/tests/test_ci_policy.py @@ -350,7 +350,7 @@ def exec_dependencies(project): jsp = ET.parse(ROOT / 'jsp/pom.xml').getroot() jsp_properties = properties(jsp) - self.assertEqual('2.2.1', jsp_properties.findtext( + self.assertEqual('2.3.3', jsp_properties.findtext( 'p:jsp.api.baseline.version', namespaces=version.NS)) self.assertEqual('2.3.3', jsp_properties.findtext( 'p:jsp.api.version', namespaces=version.NS)) @@ -372,9 +372,9 @@ def exec_dependencies(project): jakarta = ET.parse(ROOT / 'jakarta/pom.xml').getroot() jakarta_properties = properties(jakarta) expected = { - 'jakarta.el.api.baseline.version': '4.0.0', + 'jakarta.el.api.baseline.version': '6.0.1', 'jakarta.el.api.version': '6.0.1', - 'jakarta.servlet.api.baseline.version': '6.0.0', + 'jakarta.servlet.api.baseline.version': '6.1.0', 'jakarta.servlet.api.version': '6.1.0', } for name, value in expected.items(): diff --git a/scripts/tests/test_release_baselines.py b/scripts/tests/test_release_baselines.py index 1f85a20..2dd8137 100644 --- a/scripts/tests/test_release_baselines.py +++ b/scripts/tests/test_release_baselines.py @@ -3,6 +3,7 @@ from pathlib import Path import re import subprocess +import tempfile import unittest import xml.etree.ElementTree as ET @@ -13,10 +14,11 @@ PROJECT_VERSION = re.compile(r'^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$') -def immutable_release_versions(): +def immutable_release_versions(repository=ROOT): + """Include signed release sources integrated by squash, not just ancestors.""" versions = [] tags = subprocess.check_output( - ['git', 'tag', '--merged', 'HEAD', '--list', 'v*'], cwd=ROOT, + ['git', 'tag', '--list', 'v*'], cwd=repository, text=True).splitlines() for tag in tags: match = RELEASE_TAG.match(tag) @@ -52,6 +54,50 @@ def test_next_snapshot_uses_the_completed_release(self): releases = [((1, 4, 1), '1.4.1'), ((1, 5, 0), '1.5.0')] self.assertEqual('1.5.0', preceding_release(releases, '1.5.1-SNAPSHOT')) + def test_future_release_is_not_a_baseline(self): + releases = [((1, 5, 0), '1.5.0'), ((2, 0, 0), '2.0.0')] + self.assertEqual('1.5.0', preceding_release(releases, '1.5.1-SNAPSHOT')) + + +class ReleaseTagDiscovery(unittest.TestCase): + def setUp(self): + temporary = tempfile.TemporaryDirectory() + self.addCleanup(temporary.cleanup) + self.repository = Path(temporary.name) + self.git('init', '--quiet') + self.git('commit', '--quiet', '--allow-empty', '-m', 'Initial fixture') + + def git(self, *arguments): + return subprocess.check_output([ + 'git', '-c', 'user.name=Release test', + '-c', 'user.email=release-test@example.invalid', + '-c', 'commit.gpgSign=false', '-c', 'tag.gpgSign=false', + '-c', 'core.hooksPath=/dev/null', *arguments, + ], cwd=self.repository, text=True, stderr=subprocess.STDOUT).strip() + + def test_squash_merged_release_tag_is_discovered(self): + base = self.git('rev-parse', 'HEAD') + self.git('tag', '-a', 'v1.4.1', '-m', 'Previous release') + self.git('checkout', '--quiet', '--detach') + self.git('commit', '--quiet', '--allow-empty', '-m', 'Tested release') + self.git('tag', '-a', 'v1.5.0', '-m', 'Released source') + self.git('checkout', '--quiet', '--detach', base) + self.git('commit', '--quiet', '--allow-empty', '-m', 'Squash merge') + self.assertNotIn('v1.5.0', self.git('tag', '--merged', 'HEAD').splitlines()) + versions = immutable_release_versions(self.repository) + self.assertEqual('1.5.0', preceding_release(versions, '1.5.1-SNAPSHOT')) + self.assertEqual('1.4.1', preceding_release(versions, '1.5.0')) + + def test_nonrelease_tags_are_ignored(self): + for tag in ('v1.5.0', 'v2.0.0-rc1', 'v99.0', 'notes', 'v1.5.0-extra'): + self.git('tag', tag) + self.assertEqual([((1, 5, 0), '1.5.0')], + immutable_release_versions(self.repository)) + + def test_missing_release_tags_fail_closed(self): + with self.assertRaisesRegex(ValueError, 'No immutable'): + immutable_release_versions(self.repository) + class PublicApiBaseline(unittest.TestCase): def test_japicmp_uses_preceding_immutable_release(self): From c0fc1098ba1fae37640ccd5906e7bc882d64b51f Mon Sep 17 00:00:00 2001 From: Jim Manico Date: Mon, 28 Sep 2026 14:15:23 -0700 Subject: [PATCH 2/2] Fix Jackson in the fixture build plugin and link published Javadocs --- .github/DEPENDENCY_DECISIONS.md | 19 +++++++++++++++++++ CHANGELOG.md | 3 +++ README.md | 4 ++++ jakarta-test/pom.xml | 4 ++++ releases/1.5.0-central-publication.md | 8 ++++++-- scripts/tests/test_ci_policy.py | 22 ++++++++++++++++++++++ 6 files changed, 58 insertions(+), 2 deletions(-) diff --git a/.github/DEPENDENCY_DECISIONS.md b/.github/DEPENDENCY_DECISIONS.md index 7b3dce8..379aa26 100644 --- a/.github/DEPENDENCY_DECISIONS.md +++ b/.github/DEPENDENCY_DECISIONS.md @@ -44,6 +44,25 @@ Its old support classpaths therefore use JSP 2.3.3, Jakarta Servlet 6.1.0 and EL 6.0.1, matching that release. This does not change the independent minimum consumer fixtures or the published provided dependencies. +## Post-release Jackson build-plugin fix — 2026-09-28 + +GitHub's Dependabot alerts for +[GHSA-q4xh-88c3-wmh7](https://github.com/FasterXML/jackson-databind/security/advisories/GHSA-q4xh-88c3-wmh7) +and [GHSA-wjgm-6hv5-3cvf](https://github.com/FasterXML/jackson-databind/security/advisories/GHSA-wjgm-6hv5-3cvf) +surfaced after 1.5.0 publication. Both advisories identify Jackson 3.1.6 as the fixed 3.1 release. +The unpublished Jakarta fixture's executed `spring-boot-maven-plugin:4.1.1` +depends on `spring-boot-buildpack-platform:4.1.1`, which brings in Jackson +databind/core 3.1.5. Pin both to **3.1.6** directly in that plugin's dependencies. +Application dependency management does not control Maven plugin realms. + +The resolved fixture compile/runtime/test tree has no Jackson databind; its +existing JSP-only web starter excludes the JSON starter. Jackson annotations +remain test-only via Testcontainers. The core library's independent test-only +Jackson 2.22.3 is outside the two affected 2.x ranges. No application exclusion, +security suppression or published library dependency is added or changed. +Verify both the resolved plugin closure and the packaged browser fixture in CI; +a source-POM pin alone does not demonstrate the executed dependency version. + ## Deferred proposals and reconsideration conditions | Proposal | Disposition and required evidence before reconsideration | diff --git a/CHANGELOG.md b/CHANGELOG.md index 59ad786..f80e420 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ unchanged. [1.5.0 is available from Central](releases/1.5.0-central-publication. - Discover release tags independently of commit ancestry so squash merges cannot leave the compatibility baseline stale; add isolated Git regressions. - Record verified 1.5.0 publication and replace pending-availability notices. +- Update Jackson core/databind to 3.1.6 in the unpublished Jakarta fixture's + Spring Boot Maven plugin realm for GHSA-q4xh-88c3-wmh7 and GHSA-wjgm-6hv5-3cvf. + Published library dependencies and release artifacts are unchanged. ## 1.5.0 — 2026-09-28 UTC diff --git a/README.md b/README.md index 513619f..d44cfff 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,10 @@ on the same classpath or module path. See the [runtime matrix](compatibility/REA `encoder-esapi` was retired after 1.4.1 and is not included or supported in 1.5.0. Applications using it must [migrate away from the adapter](docs/encoder-esapi-retirement.md). +Published 1.5.0 API documentation: [core](https://javadoc.io/doc/org.owasp.encoder/encoder/1.5.0/), +[javax JSP](https://javadoc.io/doc/org.owasp.encoder/encoder-jsp/1.5.0/) and +[Jakarta JSP](https://javadoc.io/doc/org.owasp.encoder/encoder-jakarta-jsp/1.5.0/). + ```java import org.owasp.encoder.Encode; diff --git a/jakarta-test/pom.xml b/jakarta-test/pom.xml index b8facab..1de3ce6 100644 --- a/jakarta-test/pom.xml +++ b/jakarta-test/pom.xml @@ -26,6 +26,8 @@ 11.0.26 4.49.0 + + 3.1.6 1.5.1-SNAPSHOT @@ -206,6 +208,8 @@ org.springframework.boot spring-boot-maven-plugin + tools.jackson.corejackson-databind${jackson.build.version} + tools.jackson.corejackson-core${jackson.build.version} org.apache.commonscommons-lang33.20.0 org.codehaus.plexusplexus-utils3.6.2 diff --git a/releases/1.5.0-central-publication.md b/releases/1.5.0-central-publication.md index 77127d2..be3300c 100644 --- a/releases/1.5.0-central-publication.md +++ b/releases/1.5.0-central-publication.md @@ -71,7 +71,11 @@ Java 8, 11, 17, 21 and 25. The complete open-issue, pull-request and Dependabot inventories were empty at **20:19:55 UTC**; no alert was dismissed. Publication is complete. Main resumes at `1.5.1-SNAPSHOT` with the immutable -1.5.0 compatibility baseline. Website updates and Javadoc indexing are separate -from verified artifact availability. Pre-publication notices in the immutable +1.5.0 compatibility baseline. Javadoc indexing was refreshed and the rendered +1.5.0 [core](https://javadoc.io/doc/org.owasp.encoder/encoder/1.5.0/), +[JSP](https://javadoc.io/doc/org.owasp.encoder/encoder-jsp/1.5.0/) and +[Jakarta](https://javadoc.io/doc/org.owasp.encoder/encoder-jakarta-jsp/1.5.0/) +API pages were checked. Website maintenance remains separate from artifact +publication. Pre-publication notices in the immutable source tag remain historical; this later record confirms publication without altering those sources or their signatures. diff --git a/scripts/tests/test_ci_policy.py b/scripts/tests/test_ci_policy.py index b056bf5..cdbca3f 100644 --- a/scripts/tests/test_ci_policy.py +++ b/scripts/tests/test_ci_policy.py @@ -263,6 +263,28 @@ def test_only_executed_plugins_are_submitted(self): self.assertLess(workflow.index('Resolve shared library build plugins'), workflow.index(app_command)) + def test_boot_plugin_jackson_fix_stays_in_its_own_realm(self): + app = ET.parse(ROOT / 'jakarta-test/pom.xml').getroot() + self.assertEqual('3.1.6', app.findtext( + 'p:properties/p:jackson.build.version', namespaces=version.NS)) + plugins = app.findall('p:build/p:plugins/p:plugin', version.NS) + boot = next(plugin for plugin in plugins + if plugin.findtext('p:artifactId', namespaces=version.NS) + == 'spring-boot-maven-plugin') + jackson = { + dep.findtext('p:artifactId', namespaces=version.NS): + dep.findtext('p:version', namespaces=version.NS) + for dep in boot.findall('p:dependencies/p:dependency', version.NS) + if dep.findtext('p:groupId', namespaces=version.NS) == 'tools.jackson.core' + } + self.assertEqual({ + 'jackson-core': '${jackson.build.version}', + 'jackson-databind': '${jackson.build.version}', + }, jackson) + for dep in app.findall('p:dependencies/p:dependency', version.NS): + self.assertNotEqual('tools.jackson.core', dep.findtext( + 'p:groupId', namespaces=version.NS)) + def test_consumer_fixture_downloader_uses_submitted_patched_realm(self): workflow = (ROOT / '.github/workflows/dependency-submission.yaml').read_text() fixture_command = '-f compatibility/dependencies/pom.xml'