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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/CI_SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ snapshot API. It builds its own checkout without caches or imported artifacts.
Separate correlators submit the normal reactor and the optional Jakarta profile.
The pinned Maven submission action includes all resolved project scopes,
including runtime, test and provided dependencies. Maven dependency plugin
3.9.0 `resolve-plugins` separately resolves build/report plugins and their
3.11.0 `resolve-plugins` separately resolves build/report plugins and their
transitives; `scripts/build-dependency-snapshot.py` submits those edges as
development dependencies. Graph reports and submission JSON are retained for
inspection. Inspect representative ESAPI/AntiSamy HTTP transitives and Jakarta
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Test CI policy boundaries
run: python3 -m unittest discover -s scripts/tests
- name: Verify clean reactor including the required Docker/browser test
run: mvn -B -ntp clean verify -PtestJakarta 2>&1 | tee build.log
run: ./mvnw -B -ntp clean verify -PtestJakarta 2>&1 | tee build.log
- name: Confirm the Jakarta application contains this reactor's exact JAR
run: |
python3 - <<'PY'
Expand All @@ -66,6 +66,8 @@ jobs:
**/target/surefire-reports/
**/target/failsafe-reports/
**/target/jsp-engine/
**/target/site/jacoco/
**/target/checkstyle-result.xml
jakarta-test/target/packaged-war.log

esapi-compatibility:
Expand Down Expand Up @@ -100,7 +102,7 @@ jobs:
java-version: '17'
distribution: 'temurin'
- name: Test ESAPI compatibility
run: mvn -B -ntp -pl esapi -am verify -Desapi.version=${{ matrix.esapi-version }}
run: ./mvnw -B -ntp -pl esapi -am verify -Desapi.version=${{ matrix.esapi-version }}

gate:
name: Java CI gate
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
build-mode: ${{ matrix.build-mode }}
- name: Compile all libraries and the optional Jakarta application
if: matrix.language == 'java-kotlin'
run: mvn -B -ntp clean package -PtestJakarta -DskipTests
run: ./mvnw -B -ntp clean package -PtestJakarta -DskipTests
- uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
category: /language:${{ matrix.language }}
Expand Down
41 changes: 35 additions & 6 deletions .github/workflows/consumer-compatibility.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
distribution: temurin
java-version: '17'
- name: Verify libraries, Java 8 API signatures, and public API compatibility
run: mvn -B -ntp clean verify 2>&1 | tee build.log
run: ./mvnw -B -ntp clean verify 2>&1 | tee build.log
- name: Prepare isolated packaged consumers
run: python3 compatibility/consumers.py prepare --repository "$RUNNER_TEMP/m2" 2>&1 | tee prepare.log
- name: Verify artifact guards reject broken packages
Expand All @@ -58,6 +58,7 @@ jobs:
**/target/failsafe-reports/
**/target/jsp-engine/
**/target/japicmp/
**/target/site/jacoco/

runtime:
name: Packaged consumers on Java ${{ matrix.java }}
Expand Down Expand Up @@ -114,9 +115,9 @@ jobs:
8
17
- name: Build with JDK 17
run: mvn -B -ntp -DskipTests install -pl core,jsp,esapi -am 2>&1 | tee build.log
run: ./mvnw -B -ntp -DskipTests install -pl core,jsp,esapi -am 2>&1 | tee build.log
- name: Run unit tests and collect coverage with Java 8
run: mvn -B -ntp -pl core,jsp,esapi jacoco:prepare-agent@prepare-agent surefire:test -Djvm="$JAVA_HOME_8_X64/bin/java" 2>&1 | tee java8-tests.log
run: ./mvnw -B -ntp -pl core,jsp,esapi jacoco:prepare-agent@prepare-agent surefire:test jacoco:report -Djvm="$JAVA_HOME_8_X64/bin/java" 2>&1 | tee java8-tests.log
- name: Confirm Java 8 execution and coverage in every tested module
run: |
for module in core jsp esapi; do
Expand All @@ -140,6 +141,9 @@ jobs:
core/target/surefire-reports/
jsp/target/surefire-reports/
esapi/target/surefire-reports/
core/target/site/jacoco/
jsp/target/site/jacoco/
esapi/target/site/jacoco/
core/target/jacoco.exec
jsp/target/jacoco.exec
esapi/target/jacoco.exec
Expand All @@ -166,7 +170,7 @@ jobs:
distribution: temurin
java-version: ${{ matrix.java }}
- name: Verify libraries on a newer build JDK
run: mvn -B -ntp clean verify 2>&1 | tee build.log
run: ./mvnw -B -ntp clean verify 2>&1 | tee build.log
- name: Preserve build diagnostics including compiler warnings
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
Expand All @@ -178,11 +182,36 @@ jobs:
**/target/failsafe-reports/
**/target/jsp-engine/
**/target/japicmp/
**/target/site/jacoco/

wrapper:
name: Maven wrapper on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
distribution: temurin
java-version: '17'
- name: Bootstrap Unix wrapper and reject wrong distribution hash
if: runner.os != 'Windows'
run: python3 scripts/check-wrapper.py
- name: Bootstrap Windows wrapper and reject wrong distribution hash
if: runner.os == 'Windows'
shell: pwsh
run: python scripts/check-wrapper.py

gate:
name: Packaged consumer gate
if: ${{ always() }}
needs: [prepare, runtime, java8-unit-tests]
needs: [prepare, runtime, java8-unit-tests, wrapper]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
Expand All @@ -192,4 +221,4 @@ jobs:
- name: Require artifact preparation, every runtime and Java 8 unit tests
env:
NEEDS: ${{ toJSON(needs) }}
run: python3 scripts/check-ci-gate.py prepare runtime java8-unit-tests
run: python3 scripts/check-ci-gate.py prepare runtime java8-unit-tests wrapper
12 changes: 10 additions & 2 deletions .github/workflows/dependency-submission.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,22 @@ jobs:
- name: Resolve build plugins and their dependencies
env:
PROFILE: ${{ matrix.profile }}
run: mvn -B -ntp ${PROFILE:+"$PROFILE"} org.apache.maven.plugins:maven-dependency-plugin:3.9.0:resolve-plugins -DoutputFile=target/build-dependencies.txt
run: ./mvnw -B -ntp ${PROFILE:+"$PROFILE"} org.apache.maven.plugins:maven-dependency-plugin:3.11.0:resolve-plugins -DoutputFile=target/build-dependencies.txt
- name: Submit build graph
env:
GH_TOKEN: ${{ github.token }}
GRAPH: ${{ matrix.graph }}
run: |
python3 scripts/build-dependency-snapshot.py --correlator "encoder-build-$GRAPH" --output target/build-snapshot.json
gh api --method POST "repos/$GITHUB_REPOSITORY/dependency-graph/snapshots" --input target/build-snapshot.json
- name: Resolve and submit the release plugin graph without signing or publishing
if: matrix.graph == 'libraries'
env:
GH_TOKEN: ${{ github.token }}
run: |
./mvnw -B -ntp -Psign-artifacts dependency:resolve-plugins -DoutputFile=target/build-dependencies.txt
python3 scripts/build-dependency-snapshot.py --correlator encoder-build-release --output target/release-build-snapshot.json
gh api --method POST "repos/$GITHUB_REPOSITORY/dependency-graph/snapshots" --input target/release-build-snapshot.json
- name: Preserve resolved graphs
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
Expand All @@ -74,4 +82,4 @@ jobs:
path: |
**/target/*dependency*.json
**/target/build-dependencies.txt
target/build-snapshot.json
target/*build-snapshot.json
1 change: 1 addition & 0 deletions .mvn/maven.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--strict-checksums
4 changes: 4 additions & 0 deletions .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
distributionSha256Sum=5af3b743dd8b876b5c45da33b676251e5f1687712644abb4ee519ca56e1d89ce
101 changes: 101 additions & 0 deletions BUILDING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Building and checking Java Encoder

Use JDK 17+ and the committed `./mvnw` (`mvnw.cmd` on Windows). The wrapper is
Apache Maven Wrapper 3.3.4's unmodified `only-script` distribution; no wrapper
JAR executes before the download check. It pins Maven 3.9.16 and its SHA-256.
The downloaded Maven ZIP was independently compared to the SHA-512 served at
[Apache's distribution site](https://downloads.apache.org/maven/maven-3/3.9.16/binaries/).
Wrapper archive SHA-256: `6cb584c2bc907b849a0b931d8266d3ff3214cdd3127115ed4f49fb7176413d36`.
Both bootstrap paths are CI gates, including a deliberately wrong checksum with
an empty wrapper cache. `.mvn/maven.config` requires strict transfer checksums.
These checks detect corruption against the recorded hash; checksums fetched from
the same publisher do not independently establish publisher identity. Review
wrapper scripts, distribution URLs and hashes together when upgrading.

```sh
./mvnw -B -ntp clean verify
./mvnw -B -ntp clean verify -PtestJakarta # requires Docker
python3 compatibility/consumers.py prepare --repository /path/to/isolated/m2
python3 compatibility/consumers.py run --runtime 17
```

Run from the root, with `-pl core -am`, or from a module using `../mvnw`.
The wrapper's `.mvn` root also anchors Checkstyle paths. Maven's JVM must be 17+
(Maven 3.9.16+); Java 8 is a **forked unit-test/consumer JVM**, never the build JVM.
Newer JDK build jobs remain advisory. Library class files retain releases 8/9.
The five library POMs share one Enforcer execution: tool minimums, duplicate
coordinates, dependency convergence, upper bounds and explicit plugin versions.
The separate Boot application applies those rules under its own parent/BOM.

## Source policy

Checkstyle plugin 3.6.0 with engine 12.3.1 checks main sources during validate:
headers, whitespace/newlines, illegal/redundant/unused imports, empty statements,
equals/hashCode and file/type names. No method-size rule forces encoder-loop
refactoring. Test sources remain out of scope. Checkstyle's current 13/14 engine
requires Java 21; 12.3.1 is the explicit Java 17 compatibility exception, not a
claim of upstream support for older engines. Review migration when the build JDK
changes. Its parser cannot parse module declarations, so `module-info.java` is
excluded from Checkstyle; compiler, packaged descriptor/source guards and actual
JPMS consumers cover it. Headers were added to those four descriptors and four
app files using their 2024 Jeremy Long introduction commits. All existing BSD
notices and original attribution remain. TLD license comments remain intact;
JSP server-side comments do not emit output. The app declares the same BSD license.

## Coverage

Normal `verify` writes HTML/XML/CSV in each library's `target/site/jacoco` and
checks per-module floors. The empty aggregator has no classes/data and is skipped.
Coverage measures unit-test execution only. Failsafe packaged/OSGi consumers and
forked JSP engines deliberately have no agent; neither do isolated runtime jobs.
Surefire uses late evaluation of both the prepared agent and caller `argLine`.
Empty defaults support `-Djacoco.skip=true`. Appending execution data intentionally
unions successive unit JVMs in one build; use `clean` for an independent baseline.
CI's Java 8 run starts in its own job/cache and uploads its own reports/data.

| Module | Measured lines | Measured branches | Line floor | Branch floor |
| --- | --- | --- | --- | --- |
| core | 1228/1240 (99.032%) | 890/903 (98.560%) | 99.0% | 98.5% |
| jsp | 66/66 | no branches | 100% | 100% |
| jakarta | 66/66 | no branches | 100% | 100% |
| esapi | 27/28 (96.429%) | no branches | 96.4% | 100% |

Floors round the current baseline down to 0.1 percentage points. They are not a
claim that every encoding behavior is covered. CI retains reports alongside test
results. Changes that intentionally alter these baselines require reviewed evidence.

## Retired Maven Site

The old Site/Reflow/Velocity/Doxia, FindBugs, PMD, JXR and report-only bindings
were dormant. Unique core/JSP examples moved to [docs/usage.md](docs/usage.md).
README/module docs and attached source/Javadoc JARs remain supported. Build-bound
Checkstyle/JaCoCo, Surefire XML, CodeQL and dependency submission replace useful
reports. Maven's implicit Site plugin is pinned to 3.22.0 and skipped to prevent
falling back to an old lifecycle default; `mvn site` is not a publishing path.
Existing GitHub Pages and the `gh-pages` branch remain available and unchanged.

## Dependency signature trust decision

Mandatory dependency/plugin PGP verification is deferred. An arbitrary key
retrieved on first use is not trusted merely because a signature verifies. A
future enforced policy needs reviewed full expected fingerprints per publisher,
rotation/revocation handling, expiring unsigned exceptions and a trusted verifier
bootstrap. A non-failing trial would only collect observations. No current rule
claims to verify the provenance of dependencies, plugins, Maven bootstrap or
extensions that execute before a verifier could run. Today the boundaries are
reviewed pins/checksums, TLS repositories, isolated caches and dependency/advisory
review. Release artifact PGP verification is a separate policy in RELEASING.md.

The measured regression probe ran only `EncodeFacadeTest` with fresh execution
data: core line coverage fell to 76.0% and branch coverage to 61.5%; both checks
failed. A separate clean `-Djacoco.skip=true` verify passed without a test-agent
argument error. The full baseline data was kept separate from that probe.

Lifecycle pins are in root `pluginManagement`, with explicit versions on API,
source-helper and signature plugins. Maven 4 prerelease plugins were deliberately
not selected for this Maven 3 build. The optional app inherits maintained plugin
pins from Boot 4.1.1 and adds explicit Enforcer/Checkstyle/disabled Site pins.
Review effective POMs for normal, `testJakarta`, and `sign-artifacts` profiles;
`dependency:resolve-plugins` feeds their resolved closures into dependency review.
Release-only publisher dependencies are submitted separately with the same
GitHub detector and a distinct correlator, so they do not hide runtime graphs.
85 changes: 85 additions & 0 deletions KEYS
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,88 @@ rWQe0hepCDvS9Fen96HEc9d/cEFQrocwgJDBOEQOi2QLuFLGrpoUa+qoCtRFW7tN
eNJraOZb9Q==
=BuF1
-----END PGP PUBLIC KEY BLOCK-----

Historical public keys
----------------------
These keys are archival, not authorized for new releases. See VERIFYING.md for
observed version mapping, expiry and source authentication. The current project
key above remains unchanged.

Versions: 1.2.2-1.2.3
Fingerprint: F9514E84AE3708288374BBBE097586CFEA37F9A6
Authentication record: Jeremy Long's OWASP Dependency-Check v6.0.0 CLI verification guide (2020)

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBFngHVEBCACWyS2Lm1Y+ia/xKYmGsYXH9Rz5i37p58GWjOmtMP1mAxh5o98M
OQV63K4/mn5uLUzkSMchIMemNVdmYqsQfA5ONJNooeqQSpGzjDOJt8RvylDNWrPs
z1QIAHc4eDCIf5qcutRom/qhKMm0IfGpyIz16TgkD6lwQdRwu/VswTQKJlabYsVJ
9Amz6xNif1BJjZLsOVAaCxuoptkfBl+vqWoXnMJAPu5m7HyrBuTry+EpKPX5vSLz
g7h1wnmF1CjOtp06Gcav+6otaZsjlpSvDKZVcUXkbnF+I4+jIowu60hB7TnHiu4w
27EbNxmYKM0F9he+hSgz7DyBR3OnS9QkPTbXABEBAAG0I0plcmVteSBMb25nIDxq
ZXJlbXkubG9uZ0BnbWFpbC5jb20+iQFUBBMBCAA+AhsDBQsJCAcCBhUICQoLAgQW
AgMBAh4BAheAFiEE+VFOhK43CCiDdLu+CXWGz+o3+aYFAl2kS0IFCQeGlPEACgkQ
CXWGz+o3+aas1wf+Ls3bTyhR4aZJMNqSEK8G+jPueZ0nmq9UiyxE5p7ACyYzZVqK
r7L/inIWqLwOtoT1OjwlfvPBUNzXuuqkCpPx8+hEJYJ1d0fpHVFXiOLxvm0ze3hT
qFYQnDRa7Qu/lgh4zQaxbXhTqUlQYEwxRr1pfsci3LKG1oRYS6igR1q6I5uUn8ou
Wb1iWr12fyKFOZsFxxFPMbufIsmf+USYk/JuuZUvE/9ThkFIY/xsuL6vZcbSFXgR
JCuPJXZ+n6nEnZJ1f/QFMQjlS27+rD1qHyo9YxXYJntigThpOBZBZbNJoYZ2+PXs
i905Gj57ytDHb3SSHxNNFeMJ/jSoxG06d8JzIQ==
=ueyh
-----END PGP PUBLIC KEY BLOCK-----

Versions: 1.3.0-1.4.0
Fingerprint: 259A55407DD6C00299E6607EFFDE55BE73A2D1ED
Authentication record: Existing Java Encoder KEYS record at b51c575 and Dependency-Check CLI guide

-----BEGIN PGP PUBLIC KEY BLOCK-----

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
=gwVj
-----END PGP PUBLIC KEY BLOCK-----
Loading
Loading