diff --git a/.gitattributes b/.gitattributes index edf4192..00ba7c0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,3 +9,6 @@ *.pdf binary *.png binary *.zip binary + +# Preserve the historical wiki snapshot byte-for-byte, including old whitespace. +docs/archive/wiki-2019/*.mediawiki -text whitespace=-blank-at-eol,-blank-at-eof diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..c6a4006 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# Verified repository administrators with write access on 2026-09-26. +# Requests review; mandatory code-owner approval is not enabled by this file. +* @jmanico @jeremylong diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..b1a09dd --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# Maintainer support and Foundation donations are distinct; see CONTRIBUTING.md. +custom: + - https://manicode.com/funding.json + - https://owasp.org/donate diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..f0d7f75 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,30 @@ +name: Ordinary bug report +description: Report a reproducible non-security bug. +title: "Bug: " +body: + - type: markdown + attributes: + value: | + **Suspected vulnerability? Stop and use [SECURITY.md](https://github.com/OWASP/owasp-java-encoder/security/policy).** + This form is public. Do not include attack proofs, credentials, personal data or private URLs. + - type: input + id: environment + attributes: + label: Artifact, version and runtime + description: Include JDK and container/framework versions when relevant. + validations: + required: true + - type: textarea + id: behavior + attributes: + label: Expected and actual behavior + description: Name the method/tag and parser context; use harmless placeholder data. + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: Minimal non-sensitive reproduction + description: Include commands or a small example, and relevant sanitized diagnostics. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..4a9aa0c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Report a suspected vulnerability privately + url: https://github.com/OWASP/owasp-java-encoder/security/policy + about: Do not put vulnerability details or proofs in public issues or pull requests. + - name: Read the output-context guide + url: https://github.com/OWASP/owasp-java-encoder/blob/main/docs/contexts.md + about: Choose an encoder for the parser receiving the value. diff --git a/.github/ISSUE_TEMPLATE/context.yml b/.github/ISSUE_TEMPLATE/context.yml new file mode 100644 index 0000000..733e619 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/context.yml @@ -0,0 +1,21 @@ +name: Output-context question +description: Ask which documented API fits an ordinary output context. +title: "Context: " +body: + - type: markdown + attributes: + value: | + This is a public discussion. Suspected encoding bypasses or vulnerabilities belong in [SECURITY.md's private channels](https://github.com/OWASP/owasp-java-encoder/security/policy). + - type: input + id: version + attributes: + label: Artifact and version + validations: + required: true + - type: textarea + id: context + attributes: + label: Surrounding syntax and question + description: Show a harmless placeholder, the template/framework and the parser receiving it. Explain any automatic escaping. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 0000000..ceee5b3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,22 @@ +name: Scoped feature proposal +description: Describe a use case and compatibility tradeoffs before implementing it. +title: "Proposal: " +body: + - type: markdown + attributes: + value: | + Read the [context guide](https://github.com/OWASP/owasp-java-encoder/blob/main/docs/contexts.md) first. A proposal is not implementation approval. Report suspected vulnerabilities privately through SECURITY.md. + - type: textarea + id: use-case + attributes: + label: Use case and existing alternatives + description: Explain the parser context and why current APIs or standard libraries do not meet the need. + validations: + required: true + - type: textarea + id: compatibility + attributes: + label: Scope and compatibility + description: Identify public API, exact-output, Unicode/null, runtime and dependency effects. No implementation is required for triage. + validations: + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..9bbb568 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ +## Change + +Describe the problem, resulting behavior and related issue. For suspected +vulnerabilities, stop and use SECURITY.md's private reporting channels. + +## Compatibility and validation + +Describe affected contexts, exact-output/API/dependency changes and migration +needs. List the relevant commands/results and any checks you could not run. + +- [ ] I kept the change scoped and preserved relevant notices. +- [ ] I checked documentation/changelog and tests for any behavior change. +- [ ] This PR contains no credentials or private vulnerability evidence. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b20fda6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,135 @@ +# Changelog + +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 publication is pending on Central](releases/1.4.1.md). + +## Unreleased — 1.5.0 + +Development builds use `1.5.0-SNAPSHOT`; this is not a published release. + +* fix: resolve ESAPI's reference encoder lazily for each delegated operation. Missing configuration no longer poisons adapter initialization; OWASP-backed operations remain usable, and delegation can recover when configuration becomes available in the same JVM. JSON methods retain upstream delegation and null behavior [#165](https://github.com/OWASP/owasp-java-encoder/pull/165). + +* fix: the ESAPI adapter's `encodeForURL` now encodes individual URL components with UTF-8, including reserved delimiters and literal `+`, instead of preserving whole-URI delimiters. Spaces remain `%20`, null remains the string `"null"`, and unpaired surrogates remain `-`. See the [migration guide](esapi/README.md#url-encoding-migration-in-15-unreleased) for output changes, form-encoding differences, and the retained quoted HTML/CSS/JavaScript contracts [#100](https://github.com/OWASP/owasp-java-encoder/issues/100). +* 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](README.md#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). +* fix: the XML 1.1 encoders (`forXml11`, `forXml11Content`, `forXml11Attribute`) now encode U+0085 (NEL) as `…` and U+2028 (line separator) as `
`, 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. + +### Build, compatibility and maintenance + +- Preserve original-JAR consumers on Java 8/11/17/21/25, explicit/automatic JPMS + and Felix R6/R8; add final TLD-surface/Writer contract checks (#162, #167). +- Test packaged javax/Jakarta TLDs through isolated Tomcat/Jasper engines; retain + required real-browser and executable-WAR checks with the modernized optional + Boot 4.1.1 fixture (#179, #180). +- Pin and guard Actions, add CodeQL/dependency submissions/Dependabot, isolate + Maven caches, and preserve required CI/security gates (#173, #177). +- Include Java 9 descriptors in source attachments; normalize source metadata + and retain attribution (#184). +- Retire the dormant Maven Site/OSS parent, adopt verified Maven 3.9.16 wrapper + and JDK 17 build policy, Checkstyle and measured unit coverage floors; isolate + signing/publishing tools, verify local bundles and measure reproducibility + (#185, #187). This does not change the Java 8 library runtime baseline. +- Add release verification, historical key evidence, maintainer custody and + release-specific ESAPI guidance (#164, #171, #185). Historical signing-key + authorization gaps (#110) and Central access/custody work (#111) remain open. + +These items are merged through `3bd86250a9c9cd48577c3bf7fb9c46dbe91c1c90`. +The [maintenance tracker](https://github.com/OWASP/owasp-java-encoder/issues/169) +records PRs, tests and dispositions; it is not approval to publish 1.5. + +## 1.4.1 — 2026-09-26 UTC + +[Signed GitHub release](https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.4.1) +([tag created 2026-09-25 in America/Los_Angeles](https://github.com/OWASP/owasp-java-encoder/tree/v1.4.1)). +**Central publication remains pending. Upgrade all four Java Encoder artifacts; +versions through 1.4.0 are affected.** + +- Fix `EncodedWriter` context corruption during buffer overflow + ([GHSA-57jg-769q-93vh](https://github.com/OWASP/owasp-java-encoder/security/advisories/GHSA-57jg-769q-93vh)). +- Fix insufficient-lookahead infinite loops in `EncodedWriter` + ([GHSA-q6jj-5396-8mq2](https://github.com/OWASP/owasp-java-encoder/security/advisories/GHSA-q6jj-5396-8mq2)). +- Fix CSS String API maximum-output sizing for long U+2028/U+2029 runs + ([GHSA-p9ff-j89j-9xhx](https://github.com/OWASP/owasp-java-encoder/security/advisories/GHSA-p9ff-j89j-9xhx)). +- Preserve Java 8 runtime, public method signatures, Maven and JPMS identities; + make adapter API dependencies transitively readable in module descriptors. +- Pin the ESAPI adapter's default to 2.7.0.0 rather than a Maven version range. + +See the [full release record](releases/1.4.1.md) for affected entry points, +coordinates, verification and publication status. Later 1.5 changes do not alter +these retained artifacts. + +## 1.4.0 — 2025-11-17 + +[Release and tag](https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.4.0). +Add XML 1.1 core APIs (#88); update tests and security documentation (#83, #86, #87). +The ESAPI POM uses `[2.5.1.0,3)`; a temporary dependency pin controls resolution but +**does not fix Java Encoder's security issues**. See the +[1.4.0 migration guidance](esapi/README.md#temporary-esapi-pin-for-140-consumers). + +## 1.3.1 — 2024-08-20 + +[Release and tag](https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.3.1). +Fix Java 8 `NoSuchMethodError` (#80) and add OSGi manifest entries (#82). + +## 1.3.0 — 2024-08-02 + +[Release and tag](https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.3.0). +Raise the library minimum to Java 8; build with JDK 17 for test dependencies. +Add historical automatic module names (#45), explicit Java 9 module descriptors +via multi-release JARs (#77), and a separate Jakarta Servlet 5 adapter (#75). +Update the ESAPI adapter (#76) and Javadocs. Javax and Jakarta remain separate +artifacts with the same tag implementation package. + +## 1.2.3 — 2020-11-08 + +[Release and tag](https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.2.3). +Make the manifest OSGi-compliant (#39) and support ESAPI 2.2+ (#37). +This and earlier libraries retained the Java 5–7 runtime baseline, unlike 1.3+. + +## 1.2.2 — 2018 + +[Tag](https://github.com/OWASP/owasp-java-encoder/tree/v1.2.2) created 2018-09-03; +the retained README announcement is dated 2018-09-14. Documentation and licensing +fixes. No separate GitHub release record exists at the 2026-09-26 inventory. + +## 1.2.1 — 2017-02-19 (tag/announcement) + +[Tag](https://github.com/OWASP/owasp-java-encoder/tree/v1.2.1). +CDATA output no longer emits intermediate characters between adjacent CDATA +sections; improve the Pages documentation. No separate GitHub release record +exists at the inventory date. + +## 1.2 — 2015-04-12 (tag/announcement) + +[Tag](https://github.com/OWASP/owasp-java-encoder/tree/v1.2). +Move the project to GitHub; the retained wiki also records removal of ThreadLocal +use from development in February 2015. No separate GitHub release record exists +at the inventory date. + +## Earlier announcements + +The [retained README](https://github.com/OWASP/owasp-java-encoder/blob/3bd86250a9c9cd48577c3bf7fb9c46dbe91c1c90/README.md#news) +records 1.1.1 on 2014-01-30 (bug fix and ESAPI integration) and 1.1 on 2013-02-14 +(encoding refinements and JSP tags/functions). These are announcement dates, +not independently established release timestamps; the old wiki dates the 1.1.1 +announcement differently. No corresponding GitHub tags/releases are present. +The March 2014 documentation update is not a software release. Original Central +artifacts and observed signatures are catalogued separately in [VERIFYING.md](VERIFYING.md). + +## Historical GitHub metadata disposition + +Checked 2026-09-26: GitHub releases exist for 1.2.3 through 1.4.1; titles vary +between `Version 1.2.3` and `v...`, and 1.4.1 identifies itself as a security +release. Keep those titles, dates and original text: they are unambiguous, and +backfilling older entries would require inventing publication timestamps. This +changelog supplies consistent navigation without rewriting history. Preserve +1.4.0's dated upgrade supplement and 1.4.1's security/pending-publication notice. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..cd2d627 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,6 @@ +# Code of Conduct + +This OWASP project follows the [OWASP Code of Conduct](https://owasp.org/policy/code-of-conduct). +The current Foundation policy defines expected conduct and its reporting process. +For conduct concerns, use the reporting route in that policy. For a suspected +software vulnerability, use the separate private channels in [SECURITY.md](SECURITY.md). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..a7a4b62 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,79 @@ +# Contributing + +Ordinary bugs, context questions, scoped proposals, tests and documentation fixes +are welcome. Read the [context contracts](docs/contexts.md), [compatibility +matrix](compatibility/README.md) and [Code of Conduct](CODE_OF_CONDUCT.md). +Report suspected vulnerabilities **privately** through [SECURITY.md](SECURITY.md), +not public issues, reproduction links or pull requests. + +## Build and check a change + +Use JDK 17, the committed Maven wrapper, and Python 3.8+ for repository checks. +Libraries target Java 8; the build JVM is not Java 8. Docker is needed only for +the optional local browser/WAR fixture, which remains a required CI job. + +```sh +./mvnw -B -ntp clean verify +python3 scripts/check-taglib-parity.py +python3 -m unittest discover -s scripts/tests +python3 compatibility/consumers.py prepare +python3 -m unittest discover -s compatibility/tests +python3 compatibility/consumers.py run --runtime 17 --java-home "$JAVA_HOME" +./mvnw -B -ntp clean verify -PtestJakarta +``` + +Set `JAVA_HOME` to the JDK used for a consumer run. Prepare consumers only after a +successful reactor verify and in an empty `target/compatibility`; `clean` removes +old preparation output. To exercise one ESAPI matrix version: + +```sh +./mvnw -B -ntp -pl esapi -am clean verify -Desapi.version=2.7.0.0 +``` + +Other supported versions and their upstream security status are separate in +[esapi/README.md](esapi/README.md). See [BUILDING.md](BUILDING.md) for the verified +wrapper, Checkstyle's actual source scope/Java 17 exception, measured coverage +floors and diagnostics. The legacy Maven Site and benchmark profiles are retired. +Use fresh execution data when checking coverage; do not lower floors just to make +a change pass. Tests and module descriptors have explicit style-check exceptions, +not a claim that all sources are checked. Preserve original license notices. + +## Pull requests and review + +Keep the change focused and describe the trigger, resulting behavior, compatibility +impact and validation. Output spelling matters: document new or removed escaping, +null/Unicode changes, affected parser contexts and migration examples. Add behavior +or parser regression tests for a contract change, including Writer boundaries where +relevant. Keep javax/Jakarta sources and packaged TLDs in parity. Public API, +bytecode, module/bundle identities and dependency scope changes need explicit review. +Update the Unreleased changelog only for changes being delivered, not open proposals. + +The current rules require one approval, dismiss stale approvals after changes, +require approval of the latest push and resolved conversations, and require the +compatibility/CI gates plus Java, Actions and Python CodeQL checks on an up-to-date +base. Named maintainers have an audit-visible **PR-only review bypass**; required +CI/security checks have no bypass. CODEOWNERS requests review from verified +maintainers; owner approval is not a separate enforced rule. AI review is useful +but is not independent maintainer approval. See [CI/security operations](.github/CI_SECURITY.md). +No DCO/sign-off requirement or new response-time guarantee is introduced here. + +Maintainers triage by reproducibility, affected context, security impact and +compatibility cost. They may request a smaller case, consolidate duplicates or +record a scoped deferral; a proposal is not implementation approval. This is a +volunteer project without a public-issue response SLA. Discussions remains disabled; +use the context-question form. Blank ordinary issues remain enabled for reports +that do not fit a form. None of these public routes is for vulnerability evidence. + +## Funding + +The existing [funding authorization](.well-known/funding-manifest-urls), merged in +[#157](https://github.com/OWASP/owasp-java-encoder/pull/157), points to +[Jim Manico's maintenance funding manifest](https://manicode.com/funding.json). +That manifest describes maintainer support through Manicode Security and its +contact/payment channels; it is not an OWASP Foundation donation page. Separately, +you can [donate to the OWASP Foundation](https://owasp.org/donate). Check the chosen +recipient and current terms directly. Contributions of tests, reviews and docs +are also valuable; funding does not determine review or security decisions. + +Release signing, access/custody and publication use [RELEASING.md](RELEASING.md) +and [MAINTAINERS.md](MAINTAINERS.md), not the normal contributor build. diff --git a/README.md b/README.md index b0067a0..8aef3f1 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,37 @@ -OWASP Java Encoder Project -========================== +# OWASP Java Encoder -![Build Status](https://github.com/OWASP/owasp-java-encoder/actions/workflows/build.yaml/badge.svg?branch=main) [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![javadoc](https://javadoc.io/badge2/org.owasp.encoder/encoder/javadoc.svg)](https://javadoc.io/doc/org.owasp.encoder/encoder) +![Build status](https://github.com/OWASP/owasp-java-encoder/actions/workflows/build.yaml/badge.svg?branch=main) +[![BSD 3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](LICENSE) -Contextual Output Encoding is a computer programming technique necessary to stop -Cross-Site Scripting. This project is a Java 8+ simple-to-use drop-in high-performance -encoder class with little baggage. +Contextual output encoding for Java 8+. Choose an encoder for the parser context +receiving untrusted text: HTML, JavaScript, CSS, XML or a URL component. The core +has no runtime dependencies; optional JSP, Jakarta and ESAPI adapters have their +own dependency graphs. Encoding is one part of [XSS prevention][xss], alongside +safe templates, URL validation and other application controls. -For more detailed documentation on the OWASP Java Encoder please visit https://owasp.org/www-project-java-encoder/. +**Upgrade all Java Encoder artifacts to 1.4.1. Versions through 1.4.0 are affected +by the [security issues fixed in 1.4.1](releases/1.4.1.md#security-fixes).** +Maven Central publication is still pending (checked 2026-09-26); the signed +[GitHub 1.4.1 release][release] is available. Download, [verify](VERIFYING.md) and +[install its retained artifacts](releases/1.4.1.md#verification) in your local or +organizational Maven repository. Central alone cannot resolve 1.4.1. Do not use +Central's affected 1.4.0 just because it is the latest version shown there. -Project Leaders ---------------- +`main` is **unreleased 1.5.0-SNAPSHOT**. Its JSON API, JavaScript template support, +XML 1.1 tag bindings and ESAPI URL change are described below with version labels; +they are not features of the signed 1.4.1 release. See [CHANGELOG.md](CHANGELOG.md). -- [Jim Manico](https://github.com/jmanico) -- [Jeremy Long](https://github.com/jeremylong) +## Start using the OWASP Java Encoders -See [MAINTAINERS.md](MAINTAINERS.md) for responsibilities, signing-key custody, -and recovery readiness. +After installing the verified 1.4.1 artifacts, select the dependency you need. +All four use group ID `org.owasp.encoder` and version `1.4.1`: -Start using the OWASP Java Encoders ------------------------------------ -**Maven Central publication is pending.** Version 1.4.1 is available as signed -artifacts from the [GitHub security release](https://github.com/OWASP/owasp-java-encoder/releases/tag/v1.4.1). -Until Central publication completes, [download and verify those artifacts](releases/1.4.1.md#verification) and -install them in your local or organizational Maven repository; the dependency -examples below require that installation. Maven Central 1.4.0 remains affected. - -The core library's [Maven Central listing](https://central.sonatype.com/artifact/org.owasp.encoder/encoder) -currently offers releases through 1.4.0. - -The JSP tag and EL function libraries have Central listings as well; their -1.4.1 artifacts are available from the signed GitHub release while publication -is pending: - -- [encoder-jakarta-jsp](https://central.sonatype.com/artifact/org.owasp.encoder/encoder-jakarta-jsp) - Jakarta Servlet 5.0+ -- [encoder-jsp](https://central.sonatype.com/artifact/org.owasp.encoder/encoder-jsp) - legacy `javax.servlet` API - -After installing the verified 1.4.1 artifacts, use these dependencies: +| Artifact ID | Purpose and runtime dependencies | +| --- | --- | +| `encoder` | Core String/Writer API; no runtime dependencies | +| `encoder-jsp` | Legacy `javax` JSP tags/EL functions; core plus container-provided JSP API | +| `encoder-jakarta-jsp` | Jakarta JSP tags/EL functions; core plus container-provided Jakarta JSP API | +| `encoder-esapi` | ESAPI `Encoder` adapter; core and ESAPI 2.7.0.0 with its transitive dependencies | ```xml @@ -44,253 +39,138 @@ After installing the verified 1.4.1 artifacts, use these dependencies: encoder 1.4.1 - - - - org.owasp.encoder - encoder-jakarta-jsp - 1.4.1 - - - - - org.owasp.encoder - encoder-jsp - 1.4.1 - ``` -Quick Overview --------------- -The OWASP Java Encoder library is intended for quick contextual encoding with very little -overhead, either in performance or usage. To get started, add the `encoder` dependency shown -above and import `org.owasp.encoder.Encode`. - -Example usage: +Replace `encoder` with one adapter artifact ID when needed; each adapter brings +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 [ESAPI dependency and migration +policy](esapi/README.md), [runtime matrix](compatibility/README.md), and +[dependency/license inventory](docs/dependencies.md). Development snapshots are +not security releases or a substitute for the signed 1.4.1 artifacts. ```java -PrintWriter out = ...; -out.println(""); -``` - -Please look at the javadoc for Encode to see the variety of contexts for which you can encode. - -Happy Encoding! +import org.owasp.encoder.Encode; -Security --------- -Please report suspected vulnerabilities privately. See [SECURITY.md](SECURITY.md) for -the reporting channels, supported versions, and scope. Verify downloads using the -[public release keys](KEYS) and [signature/checksum guide](VERIFYING.md). - -Building --------- - -Use JDK 17 to build, package, and test the project. The 1.x libraries retain a -Java 8 API and bytecode baseline (`--release 8`); test applications and servlet -containers can require newer Java versions. Packaged consumers run in CI on Java -8, 11, 17, 21, and 25. See [runtime support and compatibility checks](compatibility/README.md) -for per-artifact requirements, fixture scope, and advisory newer-JDK builds. -If a future javac removes `--release 8`, a runtime baseline change requires a -future-major-version decision; it does not change the 1.x baseline. Simply run: - -```shell -./mvnw verify +out.write("

"); +Encode.forHtmlContent(out, userText); // Writer overload; no intermediate String +out.write("

"); ``` -To validate that the Jakarta JSP tags and EL functions work correctly, run the integration test: - -```shell -./mvnw verify -PtestJakarta +The equivalent String call is `Encode.forHtmlContent(userText)`. Callers supply +trusted surrounding syntax and attribute quotes. Encode raw data once, at the +output boundary; account for any escaping your template engine already performs. + +## Choose the output context + +| Destination | API and limits | +| --- | --- | +| HTML text, including textarea content | `forHtmlContent`; `forHtml` also covers quoted ordinary text attributes | +| Quoted HTML text attribute | `forHtmlAttribute`; not an event-handler expression or URL validator | +| One raw URL component | `forUriComponent`; assemble with trusted delimiters, validate the URL, then encode for the enclosing HTML attribute | +| JavaScript string | `forJavaScript`; supply single/double quotes. Ordinary untagged template literal text requires **1.5**. Never use in tagged templates, expression bodies, JSON or script URLs | +| JSON string content | `forJson` (**1.5**); supply double quotes. Prefer a serializer for a complete document | +| Quoted CSS string / CSS `url(...)` value | `forCssString` / `forCssUrl`; validate URLs and obey the method's surrounding-context rules | +| XML 1.0 text / quoted attribute | `forXmlContent` / `forXmlAttribute`; `forXml` covers both | +| XML 1.1 text / quoted attribute | `forXml11Content` / `forXml11Attribute` (core **1.4+**); requires an XML 1.1 document/parser, not HTML | +| XML CDATA / comment | `forCDATA` / `forXmlComment`; not HTML comments | +| Java source string literal | `forJava`; caller supplies quotes; unpaired surrogates may not compile | + +Every listed facade method has String and Writer overloads. The +[context guide](docs/contexts.md) explains nesting, null/Unicode behavior, +JavaScript variants, template boundaries, JSON and unsafe contexts. The +[Java/JSP examples](docs/usage.md) show complete surrounding syntax. + +Encoding does not sanitize HTML, validate input/URLs, serialize JSON documents, +perform SQL parameterization, or decode/canonicalize data. Use an HTML sanitizer +when markup must be allowed; use parameterized queries for SQL. See the +[OWASP Java security-library guide][java-libraries] for these distinct roles. + +## Taglib + +Taglib URIs are **identifiers**, not URLs that must open in a browser: + +| Adapter | Basic identifier | Advanced identifier | +| --- | --- | --- | +| Jakarta | `owasp.encoder.jakarta` | `owasp.encoder.jakarta.advanced` | +| javax JSP | `https://www.owasp.org/index.php/OWASP_Java_Encoder_Project` | Same identifier with `#advanced` appended | + +```jsp +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %> +<%@ taglib prefix="e" uri="owasp.encoder.jakarta" %> +

${e:forHtmlContent(param.message)}

``` -The integration test requires a running Docker-compatible container runtime. - -Java 9+ Module Names --------------------- - -| JAR | Explicit JPMS Module | Automatic-Module-Name | -|---------------------|-----------------------|--------------------------| -| encoder | owasp.encoder | org.owasp.encoder | -| encoder-jakarta-jsp | owasp.encoder.jakarta | org.owasp.encoder.jakarta | -| encoder-jsp | owasp.encoder.jsp | org.owasp.encoder.jsp | -| encoder-esapi | owasp.encoder.esapi | org.owasp.encoder.esapi | - -The multi-release descriptors define the explicit Java 9+ module names. The -manifest names intentionally retain their historical values for consumers that -disable multi-release support or otherwise use automatic-module discovery. - -The adapter modules also require their public API dependency on the module path: - -| Adapter module | Required dependency module | Supported Maven artifact | -|---------------------------|----------------------------|-------------------------------------------------------| -| `owasp.encoder.jsp` | `javax.servlet.jsp.api` | `javax.servlet.jsp:javax.servlet.jsp-api:2.2.1` | -| `owasp.encoder.jakarta` | `jakarta.servlet.jsp` | `jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.0.0` | -| `owasp.encoder.esapi` | `esapi` | `org.owasp.esapi:esapi:2.7.0.0` | - -These dependencies are transitive in the module descriptors because their types -appear in the adapters' public APIs. The JSP and ESAPI dependencies are automatic -modules; use the original Maven artifact filenames so Java derives the module -names shown above. Servlet containers continue to provide the JSP APIs at runtime, -and classpath-based applications are unaffected. - -The ESAPI adapter's fixed dependency and tested compatibility policy are -documented in [esapi/README.md](esapi/README.md). - - -OSGi Bundles ------------- - -| JAR | Bundle-SymbolicName | Export-Package | Imports `org.owasp.encoder` | Imports API packages | -|---------------------|---------------------------------|--------------------------|-----------------------------|-------------------------------------------------------------| -| encoder | `org.owasp.encoder` | `org.owasp.encoder` | (none) | (none) | -| encoder-jsp | `org.owasp.encoder.jsp` | `org.owasp.encoder.tag` | `[1.5,2)` | `javax.servlet.jsp`, `javax.servlet.jsp.tagext`: `[2.0,3)` | -| encoder-jakarta-jsp | `org.owasp.encoder.jakarta-jsp` | `org.owasp.encoder.tag` | `[1.5,2)` | `jakarta.servlet.jsp`, `jakarta.servlet.jsp.tagext`: `[3.0,4)` | -| encoder-esapi | `org.owasp.encoder.esapi` | `org.owasp.encoder.esapi`| `[1.4.1,2)` | `org.owasp.esapi.*`: unversioned | - -The symbolic names are fixed; note that the Jakarta bundle's differs from its -`Automatic-Module-Name`. Core exports `org.owasp.encoder` at its release version. -The JSP and Jakarta tags require core 1.5 because they call `Encode.forJson`; the -ESAPI adapter only calls older methods, so its floor is the oldest supported core, -the 1.4.1 security release. Jakarta Pages 4 is not in the accepted range until -compatibility with it has been verified. ESAPI publishes no OSGi metadata: OSGi -users must wrap ESAPI and its dependencies as bundles themselves. The project's -tests supply the ESAPI packages from the framework host, which is not a statement -that upstream ESAPI supports OSGi. - -TagLib --------------------- - -| Lib | 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 ---------------------- - -`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 - - ``` - -- 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), enforce application-specific restrictions on its destination and - path, and then encode the whole value for the enclosing context. Parsing alone - does not establish safety: - - ```jsp - - ``` - -`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). - -The ESAPI adapter's `encodeForURL` changes separately in unreleased 1.5: it now -uses `forUriComponent`, escaping URL delimiters while retaining `%20` for spaces. -Pass raw component data, not a complete or already encoded URL. See the -[adapter migration and context contracts](esapi/README.md#url-encoding-migration-in-15-unreleased) -for differences from earlier adapter releases and ESAPI's reference form encoder. - -Development ------------ - -The OWASP Java Encoder project is a multi-module Maven project: - -```bash -$ ./mvnw verify +Use the javax identifier for a javax container. Tags use an empty body and a +required `value` attribute, for example ``. +See [bindings and EL evaluation](docs/usage.md#tag-bindings-and-el-evaluation) for +basic versus advanced methods and version-sensitive deployment settings. In 1.5, +advanced taglibs expose every `Encode.forX(String)` context except `forJava`; +Java source generation is not a JSP context. XML 1.1 bindings are new in 1.5. + +## Migrating from forUri + +`Encode.forUri` is deprecated in the released API. **Unreleased 1.5** extends +that deprecation to `Encoders.URI`, both `ForUriTag` classes and the `forUri` +tag/function documentation. All of these entry points are retained through 1.x. Encoding a whole URI does not validate it: +`forUri("javascript:alert(1)")` returns it unchanged. Existing `%` signs are encoded +again. Use `forUriComponent` for one raw parameter name/value, path segment or +fragment; validate complete URLs separately, then use `forHtmlAttribute` when +placing one in a quoted HTML attribute. Parsing with `java.net.URI` alone does +not establish safety. See the [worked URL example](docs/usage.md#urls). + +The ESAPI adapter's `encodeForURL` changes in **unreleased 1.5** to component +encoding, escaping delimiters and literal `+`, with `%20` spaces. Earlier adapter +releases preserve whole-URI delimiters. Its existing null and malformed-Unicode +policies remain. Read the [adapter migration guide](esapi/README.md#url-encoding-migration-in-15-unreleased) +before upgrading. Removing the legacy API needs a separately reviewed future-major +decision; deprecation is not a removal schedule. + +## Java 9+ module names and OSGi + +Use the [published module names and OSGi ranges](compatibility/README.md#published-identities-and-development-import-ranges) +and [runnable JPMS example](docs/usage.md#java-modules). Explicit multi-release +module names intentionally differ from historical automatic names. Do not rename +dependency JARs used for automatic modules. CI exercises original packaged JARs +on Java 8/11/17/21/25, classpath, JPMS and Felix R6/R8; this does not certify every +container or downstream dependency combination. + +## Building and contributing + +Build with JDK 17 and the committed wrapper (Maven 3.9.16); use `mvnw.cmd` on Windows: + +```sh +./mvnw clean verify +./mvnw clean verify -PtestJakarta # optional locally; requires Docker ``` -See [RELEASING.md](RELEASING.md) for signing, Maven Central publication, and release verification. - -When changing the version, update the root `pom.xml`, the `` version in each -module POM, and `encoder.version` in `jakarta-test/pom.xml`. CI fails if -`jakarta-test` would test a different `encoder-jakarta-jsp` version than the one being built. -When publishing a release, also update the supported versions in `SECURITY.md`. - - -News ----- -### Unreleased - 1.5.0 -Development builds use `1.5.0-SNAPSHOT`; this is not a published release. - -* fix: the ESAPI adapter's `encodeForURL` now encodes individual URL components with UTF-8, including reserved delimiters and literal `+`, instead of preserving whole-URI delimiters. Spaces remain `%20`, null remains the string `"null"`, and unpaired surrogates remain `-`. See the [migration guide](esapi/README.md#url-encoding-migration-in-15-unreleased) for output changes, form-encoding differences, and the retained quoted HTML/CSS/JavaScript contracts [#100](https://github.com/OWASP/owasp-java-encoder/issues/100). -* 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). -* fix: the XML 1.1 encoders (`forXml11`, `forXml11Content`, `forXml11Attribute`) now encode U+0085 (NEL) as `…` and U+2028 (line separator) as `
`, 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. - -### 1.4.1 Security Release -Upgrade all OWASP Java Encoder dependencies to 1.4.1. This release fixes three -security issues in CSS string encoding and `EncodedWriter` buffer handling. -See [the release notes](releases/1.4.1.md) for affected entry points, -compatibility details, and verification instructions. - -### 2025-11-17 - 1.4.0 Release -The team is happy to announce that version 1.4.0 has been released! -* feat: add XML 1.1 encoding support [#88](https://github.com/OWASP/owasp-java-encoder/pull/88). - -**Consumer update (2026-09-25):** The `encoder-esapi:1.4.0` POM uses the ESAPI -range `[2.5.1.0,3)`. Consumers temporarily remaining on 1.4.0 should apply the -[ESAPI dependency-management pin](esapi/README.md#temporary-esapi-pin-for-140-consumers). -That pin does not fix Java Encoder's security issues; upgrade all Java Encoder -dependencies to the [signed 1.4.1 security release](releases/1.4.1.md). -Central publication of 1.4.1 remains pending. - -### 2024-08-20 - 1.3.1 Release -The team is happy to announce that version 1.3.1 has been released! -* fix: add OSGi related entries in the MANIFEST.MF file [#82](https://github.com/OWASP/owasp-java-encoder/pull/82). -* fix: java.lang.NoSuchMethodError when running on Java 8 [#80](https://github.com/OWASP/owasp-java-encoder/pull/80). - -### 2024-08-02 - 1.3.0 Release -The team is happy to announce that version 1.3.0 has been released! -* Minimum JDK Requirement is now Java 8 - - Requires Java 17 to build due to test case dependencies. -* Adds Java 9 Module name via Multi-Release Jars [#77](https://github.com/OWASP/owasp-java-encoder/pull/77). -* Fixed compilation errors with the ESAPI Thunk [#76](https://github.com/OWASP/owasp-java-encoder/pull/76). -* Adds support for Servlet Spec 5 using the `jakarta.servlet.*` [#75](https://github.com/OWASP/owasp-java-encoder/pull/75). - - taglib : <%@taglib prefix="e" uri="owasp.encoder.jakarta"%> - -### 2020-11-08 - 1.2.3 Release -The team is happy to announce that version 1.2.3 has been released! -* Update to make the manifest OSGi-compliant [#39](https://github.com/OWASP/owasp-java-encoder/pull/39). -* Update to support ESAPI 2.2 and later [#37](https://github.com/OWASP/owasp-java-encoder/pull/37). - -### 2018-09-14 - 1.2.2 Release -The team is happy to announce that version 1.2.2 has been released! -* This is a minor release fixing documentation and licensing issues. - -### 2017-02-19 - 1.2.1 Release -The team is happy to announce that version 1.2.1 has been released! -* The CDATA Encoder was modified so that it does not emit intermediate characters between adjacent CDATA sections. -* The documentation on [gh-pages](https://owasp.github.io/owasp-java-encoder/) has been improved. - -### 2015-04-12 - 1.2 Release on GitHub -OWASP Java Encoder has been moved to GitHub. Version 1.2 was also released! - -### 2014-03-31 - Documentation updated -Please visit https://owasp.org/www-project-java-encoder/ to see detailed documentation and examples for each API. - -### 2014-01-30 - Version 1.1.1 released -We're happy to announce that version 1.1.1 has been released. Along with an important bug fix, we added ESAPI integration to replace the legacy ESAPI encoders with the OWASP Java Encoder. - -### 2013-02-14 - Version 1.1 released -We're happy to announce that version 1.1 has been released. Along with a few minor encoding enhancements, we improved performance, and added a JSP tag and function library. - -Build policy, wrapper provenance, source checks, and coverage are documented in [BUILDING.md](BUILDING.md). The migrated [Java/JSP examples](docs/usage.md) preserve the former Maven Site usage guide. +Normal verify includes the Docker-free JSP engines. The browser/WAR suite remains +required in CI. See [BUILDING.md](BUILDING.md) for style/coverage policy, +[CONTRIBUTING.md](CONTRIBUTING.md) for review and diagnostic commands, and +[RELEASING.md](RELEASING.md) for the distinct release gates. There is no benchmark +or Maven Site publishing profile. + +The 1.x line preserves Java 8 library APIs/bytecode, published API/module identities +and dependency scopes. Exact encoded output is also observable behavior: adding +escapes is not automatically patch-compatible. Changes need context/parser tests, +an output-change note and migration guidance when required. Security fixes can +correct unsafe behavior in a patch with explicit advisories; other compatibility +breaks require a future-major decision, not just a version label. + +## Project, security and support + +Leaders: [Jim Manico](https://github.com/jmanico) and +[Jeremy Long](https://github.com/jeremylong); original author: Jeff Ichnowski. +See [MAINTAINERS.md](MAINTAINERS.md) and the [OWASP project page][project]. +The separate OWASP website can lag this repository's release status. + +Report suspected vulnerabilities **privately** through [SECURITY.md](SECURITY.md). +Verify downloads with [KEYS](KEYS) and [VERIFYING.md](VERIFYING.md). +The project uses the [BSD 3-Clause license](LICENSE) and the +[OWASP Code of Conduct](CODE_OF_CONDUCT.md). [Funding](CONTRIBUTING.md#funding) +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.4.1 diff --git a/RELEASING.md b/RELEASING.md index 0e70678..e9d0cd8 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -64,7 +64,10 @@ existing Maven version. creating a tag. The guard is a consistency check, not release approval. 4. Update README dependency examples, the security policy's supported versions, and the release notes. Include security advisories, compatibility changes, - all Maven coordinates, signing fingerprint, and verification commands. + all Maven coordinates, signing fingerprint, and verification commands. Start + from [the release-notes template](releases/TEMPLATE.md); move only merged changes + from CHANGELOG's Unreleased section. Preserve historical notes/assets and any + pending-publication notice until exact Central artifacts have been verified. 5. Record a reviewed `project.build.outputTimestamp` (UTC timestamp of the prepared release sources) in the release POM. Never use build wall-clock time. Set `TZ=UTC`, `LC_ALL=C`, `LANG=C`, and @@ -77,7 +80,12 @@ existing Maven version. -Dmaven.repo.local= verify -PtestJakarta`. 6. Commit the release files before tagging. Verify the four binary JARs, their source and Javadoc JARs, and five POMs. The optional `jakarta-test` WAR is not a - published component. + published component. Inspect all four generated manifests and effective parent/ + module POMs: current organization/maintainer IDs, project URL, Bundle-Vendor and + Bundle-DocURL, preserved original-author attribution, and unchanged published + JPMS/automatic/OSGi identities and dependency scopes. Metadata edits affect + artifact bytes, so repeat the final clean-build payload comparison after them. + Do not retrofit metadata into already signed releases. ## Sign and stage diff --git a/compatibility/README.md b/compatibility/README.md index 01d1d3d..86f820b 100644 --- a/compatibility/README.md +++ b/compatibility/README.md @@ -132,3 +132,59 @@ requires its Java 9 descriptor at `META-INF/versions/9/module-info.java`, plus a Javadoc index in every documentation attachment. Descriptor sources are added only after compilation/resource copying; Java 8 compiler inputs and the binary multi-release layout remain unchanged. + +## Published identities and development import ranges + +The tables below describe the current **1.5 development** 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. + +### Java 9+ module names + +| JAR | Explicit JPMS Module | Automatic-Module-Name | +|---------------------|-----------------------|--------------------------| +| encoder | owasp.encoder | org.owasp.encoder | +| encoder-jakarta-jsp | owasp.encoder.jakarta | org.owasp.encoder.jakarta | +| encoder-jsp | owasp.encoder.jsp | org.owasp.encoder.jsp | +| encoder-esapi | owasp.encoder.esapi | org.owasp.encoder.esapi | + +The multi-release descriptors define the explicit Java 9+ module names. The +manifest names intentionally retain their historical values for consumers that +disable multi-release support or otherwise use automatic-module discovery. + +The adapter modules also require their public API dependency on the module path: + +| Adapter module | Required dependency module | Supported Maven artifact | +|---------------------------|----------------------------|-------------------------------------------------------| +| `owasp.encoder.jsp` | `javax.servlet.jsp.api` | `javax.servlet.jsp:javax.servlet.jsp-api:2.2.1` | +| `owasp.encoder.jakarta` | `jakarta.servlet.jsp` | `jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.0.0` | +| `owasp.encoder.esapi` | `esapi` | `org.owasp.esapi:esapi:2.7.0.0` | + +These dependencies are transitive in the module descriptors because their types +appear in the adapters' public APIs. The JSP and ESAPI dependencies are automatic +modules; use the original Maven artifact filenames so Java derives the module +names shown above. Servlet containers continue to provide the JSP APIs at runtime, +and classpath-based applications are unaffected. + +The ESAPI adapter's fixed dependency and tested compatibility policy are +documented in [esapi/README.md](../esapi/README.md). + + +### OSGi bundles + +| JAR | Bundle-SymbolicName | Export-Package | Imports `org.owasp.encoder` | Imports API packages | +|---------------------|---------------------------------|--------------------------|-----------------------------|-------------------------------------------------------------| +| encoder | `org.owasp.encoder` | `org.owasp.encoder` | (none) | (none) | +| encoder-jsp | `org.owasp.encoder.jsp` | `org.owasp.encoder.tag` | `[1.5,2)` | `javax.servlet.jsp`, `javax.servlet.jsp.tagext`: `[2.0,3)` | +| encoder-jakarta-jsp | `org.owasp.encoder.jakarta-jsp` | `org.owasp.encoder.tag` | `[1.5,2)` | `jakarta.servlet.jsp`, `jakarta.servlet.jsp.tagext`: `[3.0,4)` | +| encoder-esapi | `org.owasp.encoder.esapi` | `org.owasp.encoder.esapi`| `[1.4.1,2)` | `org.owasp.esapi.*`: unversioned | + +The symbolic names are fixed; note that the Jakarta bundle's differs from its +`Automatic-Module-Name`. Core exports `org.owasp.encoder` at its release version. +The JSP and Jakarta tags require core 1.5 because they call `Encode.forJson`; the +ESAPI adapter only calls older methods, so its floor is the oldest supported core, +the 1.4.1 security release. Jakarta Pages 4 is not in the accepted range until +compatibility with it has been verified. ESAPI publishes no OSGi metadata: OSGi +users must wrap ESAPI and its dependencies as bundles themselves. The project's +tests supply the ESAPI packages from the framework host, which is not a statement +that upstream ESAPI supports OSGi. diff --git a/core/pom.xml b/core/pom.xml index 520c4eb..c477b3d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -47,6 +47,7 @@ encoder jar + https://owasp.org/projects/java-encoder Java Encoder diff --git a/docs/archive/wiki-2019/1)-Deploy-The-OWASP-Java-Encoder.mediawiki b/docs/archive/wiki-2019/1)-Deploy-The-OWASP-Java-Encoder.mediawiki new file mode 100644 index 0000000..a5ce230 --- /dev/null +++ b/docs/archive/wiki-2019/1)-Deploy-The-OWASP-Java-Encoder.mediawiki @@ -0,0 +1,25 @@ += Deploy the Java Encoder Project = + +The OWASP Java Encoder version 1.2 is now available in central! + +[https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.owasp.encoder%22 OWASP Encoder at Maven Central]. + +== Core == +Direct Download: [http://search.maven.org/remotecontent?filepath=org/owasp/encoder/encoder/1.2/encoder-1.2.jar encoder-1.2.jar] + +== Maven for Core Encoder == + + org.owasp.encoder + encoder + 1.2 + + +== JSP Tag Library == +Direct Download: [https://search.maven.org/remotecontent?filepath=org/owasp/encoder/encoder-jsp/1.2/encoder-jsp-1.2.jar encoder-jsp-1.2.jar] + +=== Maven for JSP Tag Library === + + org.owasp.encoder + encoder-jsp + 1.2 + diff --git a/docs/archive/wiki-2019/2)-Use-the-OWASP-Java-Encoder.mediawiki b/docs/archive/wiki-2019/2)-Use-the-OWASP-Java-Encoder.mediawiki new file mode 100644 index 0000000..8d19f6b --- /dev/null +++ b/docs/archive/wiki-2019/2)-Use-the-OWASP-Java-Encoder.mediawiki @@ -0,0 +1,72 @@ += Use the Java Encoder Project = + +The general API pattern is to utilize the Java Encoder Project in your user interface code and wrap all variables added dynamically to HTML with a proper encoding function. The encoding pattern is "Encode.forContextName(untrustedData)", where "ContextName" is the name of the target context and "untrustedData" is untrusted output. + +== Basic HTML Context == + + <%= Encode.forHtml(UNTRUSTED) %> + +== HTML Content Context == + + + +== HTML Attribute context == + + + +Generally Encode.forHtml(UNTRUSTED) is also safe but slightly less efficient for the above two contexts (for textarea content and input value text) since it encodes more characters than necessary but might be easier for developers to use. + +== CSS contexts == + +
+
+ +== Javascript Block context == + + + +== Javascript Variable context == + + + +JavaScript Content Notes: Encode.forJavaScript(UNTRUSTED) is safe for the above two contexts, but encodes more characters and is less efficient. + +== Encode URL parameter values == + + +== Encode REST URL parameters == + + +== Handling an Full Untrusted URL == + +When handling a full url with the OWASP Java encoder, first verify the URL is a legal URL. + + String url = validateURL(untrustedInput); + +Then encode the URL as an HTML attribute when outputting to the page. Note the linkable text needs to be encoded in a different context. + + + <%= Encode.forHtmlContent(untrustedLinkName) %> + + +== To use in a JSP with EL == + + <%@page contentType="text/html" pageEncoding="UTF-8"%> + http://www.w3.org/TR/html4/loose.dtd"> + <%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %> + + + <e:forHtml value="${param.title}" /> + + +

${e:forHtml(param.data)}

+ + + +Other contexts can be found in the org.owasp.Encode class methods, including CSS strings, CSS urls, XML contexts, URIs and URI components. \ No newline at end of file diff --git a/docs/archive/wiki-2019/Grave-Accent-Issue.mediawiki b/docs/archive/wiki-2019/Grave-Accent-Issue.mediawiki new file mode 100644 index 0000000..0c15bf3 --- /dev/null +++ b/docs/archive/wiki-2019/Grave-Accent-Issue.mediawiki @@ -0,0 +1,69 @@ += Grave Accent Issue = + +The following describes the Grave Accent XSS issue with unpatched versions of Internet Explorer. Thank you to Rafay Baloch for bringing this to our attention and to Jeff Ichnowski for the workaround. + +== Introduction == + +The grave accent (`), ASCII 96, hex 60 ([http://en.wikipedia.org/wiki/Grave_accent wikipedia]) is subject to a critical flaw in unpatched Internet Explorer. There is no possible encoding of the character that can avoid the issue. For a more in depth presentation on the issue discussed herein, please see [http://www.slideshare.net/x00mario/the-innerhtml-apocalypse Mario Heidrech's presentation]. + +== Background == + +In Internet Explorer, the grave accent is usable as an HTML attribute quotation character, equivalent to single and double quotes. Specifically, IE treats the following as equivalent: + + <%= Encode.forHtml(textValue) %>" /> + + + + +It is an IE extension, is not in HTML specifications ([http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2 HTML4], [http://www.w3.org/TR/html5/syntax.html#attributes-0 HTML5]), and is probably not well supported in other browsers. + +== The Issue == + +The following HTML snippet, demonstrates the cross-site scripting vulnerability related to grave accents on unpatched Internet Explorer: + +
+
+ + +When this snippet is run in Internet Explorer the following steps happen: + +# Two div elements are created with id's "a" and "b" +# The script executes "a.innerHTML" which returns: + + + +# The script sets "b.innerHTML" to the value from (2) and is converted to the DOM equivalent of + + + +The XSS issue arises from IE returning a value from innerHTML that it does not parse back into the original DOM. Patched version of IE fix this issue by returning the XSS value as a double-quoted attribute. The issue is complicated by the fact that no possible encoding of the grave accent can avoid this issue. + +When... + + + +...is the input, "a.innerHTML" returns the same XSS vector as it does without the encoding. + +== Recommend Solution == + +Our recommended workaround is to update any JavaScript based innerHTML read to replace the accent grave with a numeric entity encoded form: "`". As an example, the following change to the XSS vulnerable code above fixes the issue: + + + +This can be done in any library code that reads the innerHTML. To follow how this addresses the issue, the innerHTML from step 2 of the issue is converted to: + + + +Since the browser will no longer see the grave accents as an empty attribute, it will convert the input back to a copy of its original DOM. + +== Other Possible Solutions == + +As there is no encoding option available, the following options are available to web application authors: + +# Do not use innerHTML copies +# Filter out the accent grave from any user input +# Clean up grave accents when using an innerHTML copy + +== OWASP Java Encoder Library Related Changes == + +The OWASP Java Encoder Library at its core is intended to be a XSS safe _encoding_ library. The grave accent is a legitimate and frequently used character, that cannot be encoded to avoid this bug in unpatched versions of IE. With enough user feedback, we may update the library to include one of the following options: (1) alternate, drop-in build that filters grave accents, with unchanged API, (2) new filtering methods. \ No newline at end of file diff --git a/docs/archive/wiki-2019/Home.mediawiki b/docs/archive/wiki-2019/Home.mediawiki new file mode 100644 index 0000000..66df34d --- /dev/null +++ b/docs/archive/wiki-2019/Home.mediawiki @@ -0,0 +1,51 @@ += Executive Overview = + +The OWASP Java Encoder provides: + +* Output Encoding functions to help stop XSS +* Java 1.5+ standalone library + += Introduction = + +The OWASP Java Encoder is a Java 1.5+ simple-to-use drop-in high-performance encoder class with no dependencies and little baggage. This project will help Java web developers defend against Cross Site Scripting! + +Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts (primarily JavaScript) are injected into otherwise trusted web sites. You can [https://www.owasp.org/index.php/Cross-site_Scripting_(XSS) read more about Cross Site Scripting here]. One of the primary defenses to stop Cross Site Scripting is a technique called Contextual Output Encoding. You can read more about [https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet Cross Site Scripting prevention here]. + += Contextual Output Encoding = + +Contextual Output Encoding is a computer programming technique necessary to stop [https://www.owasp.org/index.php/XSS_Prevention_Cheat_Sheet Cross Site Scripting]. This project is a Java 1.5+ simple-to-use drop-in high-performance encoder class with no dependencies and little baggage. It provides numerous encoding functions to help defend against XSS in a variety of different HTML, JavaScript, XML and CSS contexts. + += Getting Started = + +The OWASP Java Encoder library is intended for quick contextual encoding with very little overhead, either in performance or usage. To get started, simply add the encoder-1.2.jar, import org.owasp.encoder.Encode and start encoding. + +Please look at the [https://search.maven.org/remotecontent?filepath=org/owasp/encoder/encoder/1.2/encoder-1.2-javadoc.jar javadoc for Encode] to see the variety of contexts for which you can encode. Tag libraries and JSP EL functions can be found in the encoder-jsp-1.2.jar. + += Licensing = + +The OWASP Java Encoder is free to use under the [http://opensource.org/licenses/BSD-3-Clause New BSD License]. + += Mailing List = + +[https://lists.owasp.org/mailman/listinfo/owasp-java-encoder-project Java Encoder Mailing List] + += Project Leaders = +Lead Author: Jeff Ichnowski [mailto:jeff.ichnowski@gmail.com @]
+[https://www.owasp.org/index.php/User:Jeremy_Long Jeremy Long] [mailto:jeremy.long@owasp.org @]
+[https://www.owasp.org/index.php/User:Jmanico Jim Manico] [mailto:jim.manico@owasp.org @] + + += Quick Download = + +* [https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.owasp.encoder%22 All Maven Central Java Encoder Downloads] +* [https://search.maven.org/remotecontent?filepath=org/owasp/encoder/encoder/1.2.1/encoder-1.2.1.jar encoder-1.2.1.jar] +* [https://search.maven.org/remotecontent?filepath=org/owasp/encoder/encoder-jsp/1.2.1/encoder-jsp-1.2.1.jar encoder-jsp-1.2.1.jar] + += News and Events = +* (Feb 2017) 1.2.1 Released +* (Apr 2015) 1.2 Released +* (Apr 2015) Moved to GitHub +* (Feb 2015) Removed ThreadLocal use from trunk +* (20 Mar 2014) Doc additions +* (5 Feb 2014) New Wiki +* (4 Feb 2014) 1.1.1 Released \ No newline at end of file diff --git a/docs/archive/wiki-2019/README.md b/docs/archive/wiki-2019/README.md new file mode 100644 index 0000000..a47c978 --- /dev/null +++ b/docs/archive/wiki-2019/README.md @@ -0,0 +1,28 @@ +# Historical wiki archive — not current usage advice + +These four `.mediawiki` files preserve the exact latest pages from +`https://github.com/OWASP/owasp-java-encoder.wiki.git`, commit +`a10dea70c502c02d072d3d9d2dc520d7c042587a` (2019-11-26), archived 2026-09-26. +`SHA256SUMS` records their bytes. Original author attribution and content are +retained verbatim; old versions, unsafe examples and obsolete advice are not +endorsed. Use the [current guide](../../contexts.md) instead. + +The signed-in repository settings showed unrestricted wiki editing on 2026-09-26; +editing was restricted to users with push access before migration. Decision: +hide the wiki after these reviewed replacements merge. Hiding preserves the wiki +repository; do not delete its pages/history. A full local Git mirror/bundle was +also retained for recovery. This tracked snapshot independently preserves all +four latest pages. Re-enable the wiki setting to restore its UI if needed; review +its advice before making it public again. + +| Historical page | Disposition and current destination | +| --- | --- | +| Home | Java 1.5/version 1.2 claims replaced by [README](../../../README.md); original-author credit retained. News goes to [CHANGELOG](../../../CHANGELOG.md). | +| Deploy | Old download links replaced by signed 1.4.1 verification/install instructions; Central pending is explicit. No old artifact is recommended. | +| Use | HTML text/attribute, URL, JSP and Writer examples migrated to [usage](../../usage.md) and [contexts](../../contexts.md). Corrected unquoted CSS examples and the URL example that validated one variable but emitted another. | +| Grave Accent Issue | Historical unpatched-IE `innerHTML` round-trip bug; do not migrate the replacement/filter workaround into current library behavior. Prefer safe DOM text APIs and supported browsers. It is distinct from 1.5's ordinary JavaScript template-literal support. | + +Current browser coverage is the required Chrome/Selenium suite, not a guarantee +for obsolete IE parsing or arbitrary `innerHTML` transformations. The archive +preserves the old workaround for historical analysis only. External OWASP project +pages are maintained separately; changing this repository does not update them. diff --git a/docs/archive/wiki-2019/SHA256SUMS b/docs/archive/wiki-2019/SHA256SUMS new file mode 100644 index 0000000..7309c85 --- /dev/null +++ b/docs/archive/wiki-2019/SHA256SUMS @@ -0,0 +1,4 @@ +4752d37966fa28d4010f4a2447edb7d777559000692a30ec29d814ef6e7524bd 1)-Deploy-The-OWASP-Java-Encoder.mediawiki +55eba650d1cc0a2cab710342c21503ee40e0fa31bbd892ee3656d15c103789c9 2)-Use-the-OWASP-Java-Encoder.mediawiki +4608ef000d4f8b27bfebe2eea862d7a518b740728c58dd2ca8d2a6179e77e459 Grave-Accent-Issue.mediawiki +f0e63458d25543590302dc33ff0d1e029ac7471b406168f43758cb9aa249dfd8 Home.mediawiki diff --git a/docs/contexts.md b/docs/contexts.md new file mode 100644 index 0000000..1efac6f --- /dev/null +++ b/docs/contexts.md @@ -0,0 +1,108 @@ +# Output contexts and boundaries + +This guide describes current `main` (unreleased **1.5**); feature introductions +are marked below. For production use, follow the [1.4.1 distribution and security +notice](../README.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; `EncodedWriter` supports chunked input and must be closed to finish +pending input. Use the facade Writer overload when encoding one String directly. + +## Encode for the parser that receives the value + +- HTML text: `forHtmlContent`; ordinary quoted text attributes: + `forHtmlAttribute`. `forHtml` covers both with additional escapes. + Always quote attributes. `forHtmlUnquotedAttribute` exists for legacy use; + prefer fixing the template to quote its value. None of these validate attribute + names, event-handler code or URL schemes. XML comment escaping is not HTML + comment escaping; do not insert untrusted data into HTML comments. +- JavaScript: supply the string delimiters yourself. `forJavaScript` covers + string data in script blocks, script attributes and JavaScript source. + `forJavaScriptBlock` is not for HTML attributes; `forJavaScriptAttribute` targets + quoted event-handler attributes; `forJavaScriptSource` is for a standalone + JavaScript resource, not HTML. Avoid dynamic event handlers when possible. + Never put the result in an unquoted expression, identifier, `${...}` expression + body, regular expression, or `javascript:`/`data:` URL. +- CSS: `forCssString` encodes data **inside a quoted CSS string**. + `forCssUrl` encodes a URL value inside CSS `url(...)`; allow-list its scheme + and destination first. Neither accepts arbitrary selectors, property names, + numeric values or declarations. Prefer a separate stylesheet or safe DOM API; + a CSS fragment placed in an HTML attribute must also satisfy that attribute's + parsing context. Do not copy the retired wiki's unquoted `width` example. +- XML: select XML 1.0 (`forXml`, `forXmlContent`, `forXmlAttribute`) or XML 1.1 + (`forXml11`, `forXml11Content`, `forXml11Attribute`, core since **1.4.0**) + deliberately. XML 1.1 requires an XML 1.1 document declaration and compatible + parser. Some XML 1.1 control-character references (such as ``) are invalid + in XML 1.0; do not use XML encoders for HTML. + `forCDATA` and `forXmlComment` implement XML 1.0 contexts; supply their delimiters. + Invalid-character replacement and XML line-ending normalization can change data. +- Java source: `forJava` encodes string-literal content for a code generator, + not JavaScript or JSON. Supply Java quotes; malformed surrogate input is not + guaranteed to produce compilable source. This API has no JSP tag/function. + +Encode raw values once at each actual parser boundary, from the inner language +to the enclosing one. Do not apply an arbitrary chain of encoders, or run an +HTML autoescaping template over an already HTML-encoded value. If the application +needs user-authored markup, choose a policy-based HTML sanitizer; output encoding +displays markup as text. Follow the [OWASP XSS Prevention Cheat Sheet][xss]. + +## JavaScript templates — new in 1.5 + +All four `forJavaScript*` methods now escape backticks, dollar signs and opening +braces. This protects literal text in **ordinary, untagged** template literals, +including data immediately after a trusted `$`. JavaScript string values remain +the same even though the emitted escape spelling changes. The same methods +continue to support single- and double-quoted strings in their documented contexts. + +This does **not** support tagged templates such as `String.raw`, or insertion +inside a `${...}` expression. Tagged templates can observe raw escape text. +Do not use a 1.4.1 JavaScript encoder for template-literal text: this support is +unreleased 1.5 behavior. The old IE grave-accent/`innerHTML` workaround is a +separate historical browser issue, not a substitute for this contract. The +[wiki archive](archive/wiki-2019/README.md) records why that advice was retired. + +In 1.5, DEL/C1 controls use hex escapes and unpaired UTF-16 surrogates use Unicode +escapes, preserving JavaScript string values through UTF-8 output. Valid surrogate +pairs remain intact. This does not promise that every downstream system accepts +unpaired surrogates. + +## JSON string content — new in 1.5 + +`Encode.forJson` encodes **one JSON string's content**. The caller supplies the +surrounding double quotes. It uses JSON escapes rather than JavaScript `\xNN` +escapes and also escapes HTML script delimiters, allowing the quoted string in an +HTML script data block. A complete JSON document should come from a JSON serializer; +choose one configured for safe HTML embedding if it is put inside a `