diff --git a/deliverytiersuite/delivery-tier-suite/delivery-tier-distribution/src/main/conf/perc/perc-datasources.xml.sample-MYSQL-MARIADB b/deliverytiersuite/delivery-tier-suite/delivery-tier-distribution/src/main/conf/perc/perc-datasources.xml.sample-MYSQL-MARIADB index 8f592a1e6a..ad4895a831 100644 --- a/deliverytiersuite/delivery-tier-suite/delivery-tier-distribution/src/main/conf/perc/perc-datasources.xml.sample-MYSQL-MARIADB +++ b/deliverytiersuite/delivery-tier-suite/delivery-tier-distribution/src/main/conf/perc/perc-datasources.xml.sample-MYSQL-MARIADB @@ -50,7 +50,14 @@ true false false - true + + false innodb true bind diff --git a/docs/SECURITY-MITIGATIONS.md b/docs/SECURITY-MITIGATIONS.md new file mode 100644 index 0000000000..4ac2808885 --- /dev/null +++ b/docs/SECURITY-MITIGATIONS.md @@ -0,0 +1,319 @@ +# Percussion CMS Security Mitigations + +This document tracks the application-layer mitigations applied against CVEs that cannot be +closed by a dependency upgrade on the Java 1.8 line. It is the closing evidence for the +sub-tasks of [epic #73](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/73). + +Each entry links the parent epic, the sub-task issue, the GAV and CVE list, and the precise +mitigation applied. Per-CVE OWASP `dependency-check` suppressions live in +`owasp-suppressions.xml`. + +## How to read this file + +| Column | Meaning | +|---|---| +| GAV | Maven groupId : artifactId : version | +| CVE | National Vulnerability Database identifier | +| Mitigation | Where in the repo the close-the-gap code or config change lives | +| Tests | The unit test(s) that pin the mitigation in place | + +--- + +## T2.1 — Apache Tika 2.9.x hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.tika:tika-core@2.9.4` (13 CVEs) | Tika deserialization, OOM, OLE extraction | `PSTikaTextConvertor` input stream capped at 100 MB; strict parser allowlist (reject unexpected types); reject embedded scripts/OLE objects; sandbox for untrusted uploads. | n/a (manual code review) | +| `org.apache.tika:tika-parser-pdf-module@2.9.4` (2 CVEs) | PDF parsing RCE class | Same PSTikaTextConvertor strict allowlist; PDFBox 2.0.31 hardening in T2.9. | n/a (manual code review) | + +- Merged PRs: [#93](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/93) (issue [#92](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/92)), [#138](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/138) (issue [#137](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/137)). +- Tika 3.x requires Java 11+; the 15 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.2 — Apache ActiveMQ 5.16.x hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.activemq:activemq-client@5.16.8` (18 CVEs) | deserialization, OpenWire framing | Broker runs in-VM only (`vm://localhost`); `` is empty and documented as such; simpleAuthenticationPlugin with anonymousAccessAllowed=false. | n/a (manual config review) | +| `org.apache.activemq:activemq-broker@5.16.8` (12 CVEs) | broker-side advisory leak, DoS | `deleteAllMessagesOnStartup=false`; `advisorySupport=false`; `` per queue. | n/a (manual config review) | +| `org.apache.activemq:activemq-openwire-legacy@5.16.8` (2 CVEs) | legacy wire framing | Legacy transport not wired; `` empty. | n/a (manual config review) | + +- Merged PRs: [#167](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/167) (issue [#166](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/166)), [#211](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/211), [#213](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/213), [#215](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/215), [#217](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/217). +- ActiveMQ 5.19.x requires Java 11+; the 32 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.3 — Apache CXF 3.5.x hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.cxf:cxf-core@3.5.11` (13 CVEs) | logging-side RCE / OOM, WSS4J classpath confusion | `` replaced with size-limited LoggingFeature bean (LIMIT=1000, verbose=false). No WSS4J interceptors are wired in the bus. | n/a (manual config review) | +| `org.apache.cxf:cxf-rt-frontend-jaxrs@3.5.11` (4 CVEs) | JAX-RS reflection / type confusion | Same bus-level hardening. | n/a (manual config review) | +| `org.apache.cxf:cxf-rt-transports-http@3.5.11` (3 CVEs) | HTTP transport framing | Same bus-level hardening. | n/a (manual config review) | + +- Merged PR: [#169](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/169) (issue [#168](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/168)); follow-up property cleanup in [#204](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/204). +- CXF 3.6.x requires Java 11+; the 20 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.4 — Spring Framework 5.3.x + Spring Security 5.8.x hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.springframework:spring-webmvc@5.3.39` (25 CVEs) | content-type confusion, RFD, open redirects | `spring.mvc.contentnegotiation.favor-path-extension=false`; `use-fresh-handler=true`; `PSSecurityHeadersFilter` registered. | n/a (manual config review) | +| `org.springframework:spring-core@5.3.39` (19 CVEs) | logging, SpEL sandbox bypass | Same headers filter; caller-controlled SpEL not evaluated. | n/a (manual config review) | +| `org.springframework:spring-web@5.3.39` (13 CVEs) | RFD, open redirects | Same headers filter; `ResponseEntity` for downloads. | n/a (manual config review) | +| `org.springframework:spring-expression@5.3.39` (8 CVEs) | SpEL injection | SpEL not exposed to user input; `@ResponseBody` returns concrete `ResponseEntity`. | n/a (manual config review) | +| `org.springframework.security:spring-security-core@5.8.16` (31 CVEs) | authn bypass, CSRF, password encoder | `DelegatingPasswordEncoder` in use; `headers().defaultsDisabled()`; CSRF enabled (default in 5.8+); `SessionManagementFilter` configured. | n/a (manual config review) | +| `org.springframework.security:spring-security-web@5.8.16` (7 CVEs) | CSRF, response splitting | Same headers filter; CSRF default enabled. | n/a (manual config review) | +| `org.springframework.security:spring-security-config@5.8.16` (5 CVEs) | config DSL hardening | Same headers filter. | n/a (manual config review) | +| `org.springframework:spring-context@5.3.39` (3 CVEs) | context SpEL bypass | No user input reaches SpEL. | n/a (manual config review) | +| `org.springframework:spring-beans@5.3.39` (2 CVEs) | bean property path binding | Same headers filter. | n/a (manual config review) | +| `org.springframework.security:spring-security-crypto@5.8.16` (1 CVE) | bcrypt timing | PBKDF2 + BCrypt used; no password data in URL/log. | n/a (manual config review) | + +- Merged PRs: [#95](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/95) (issue [#94](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/94)), [#97](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/97) (issue [#96](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/96)), [#165](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/165) (issue [#164](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/164)). +- Spring 6.x requires Java 17+; the 114 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.5 — XStream 1.4.21 hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `com.thoughtworks.xstream:xstream@1.4.21` (37 CVEs) | Untrusted-XML RCE class | `setupDefaultSecurity()` + `XStream.addPermission(NoTypePermission.NONE)` + per-class allowlist (PR #108 shrinks `com.percussion.**` wildcard to named classes). | n/a (manual code review) | + +- Merged PRs: [#106](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/106), [#108](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/108). +- XStream 1.4.x is in maintenance mode; the 50 catalogued CVEs (37 distinct + BIT aliases) are pinned at the latest Java 1.8 line. + +## T2.6 — Apache Commons hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.commons:commons-compress@1.28.0` (11 CVEs) | zip slip, zip bomb | `ZipSlipGuard` for extraction paths; `setMaxEntrySize`; reject `..` paths. | `ZipSlipGuardTest`, `PSPathInjectionGuardTest` | +| `commons-fileupload:commons-fileupload@1.6.0` (7 CVEs) | upload DoS, header injection | `setFileCountMax` + `setHeaderEncoding` on every upload handler. | n/a (manual config review) | +| `commons-beanutils:commons-beanutils@1.11.0` (3 CVEs) | class-injection gadget | `BeanUtilsBean` class-injection guard (PR #110). | n/a (manual code review) | +| `org.apache.commons:commons-collections4@4.5.0` (2 CVEs) | transformer/predicate gadget | Input validation on every `Transformer`/`Predicate`/`Closure` chain. | n/a (manual code review) | +| `org.apache.commons:commons-email@1.6.0` (2 CVEs) | header injection | Email header validation at the call site. | n/a (manual code review) | +| `commons-collections:commons-collections@3.2.2` (2 CVEs) | deserialization gadget (EOL) | JVM-startup `org.apache.commons.collections.enableUnsafeSerialization=false` lockdown. | n/a (manual code review) | +| `commons-io:commons-io@2.21.0` (2 CVEs) | untrusted file paths | `PSPathInjectionGuard` + `ZipSlipGuard` at every file utility call site. | `PSPathInjectionGuardTest`, `ZipSlipGuardTest` | +| `commons-configuration:commons-configuration@1.10` (1 CVE) | interpolation | No user input reaches `StringSubstitutor`. | n/a (manual code review) | +| `commons-httpclient:commons-httpclient@3.1` (1 CVE) | (EOL) | Migrated to Apache HttpClient 4.x / 5.x. | n/a (manual code review) | +| `commons-lang:commons-lang@2.6` (1 CVE) | (EOL) | Migrated to `commons-lang3` 3.20.0. | n/a (manual code review) | +| `org.apache.commons:commons-text@1.15.0` (1 CVE) | `StringSubstitutor` injection | No user input reaches `StringSubstitutor`. | n/a (manual code review) | +| `org.apache.commons:commons-lang3@3.20.0` (1 CVE) | (none on this version, defensive entry) | Tracking only. | n/a | + +- Merged PRs: [#83](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/83), [#85](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/85) (issue [#84](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/84)), [#87](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/87) (issue [#86](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/86)), [#90](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/90) (issue [#89](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/89)), [#110](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/110) (issue [#109](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/109)), [#173](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/173) (issue [#172](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/172)), [#175](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/175) (issue [#174](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/174)), [#177](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/177) (issue [#176](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/176)). + +## T2.7 — Apache Tomcat 9.0.x hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.tomcat:tomcat-juli@9.0.118` (1 CVE) | Ghostcat class | AJP connector absent (production + legacy install); `PSUpgradeRemoveTomcatAJP` strips any surviving AJP connector; `SecurityListener` enabled in server.xml. | n/a (manual config review) | +| `org.apache.tomcat:tomcat-servlet-api@9.0.118` (1 CVE) | request-attribute isolation | `allowedRequestAttributesPattern` set on HTTP + HTTPS connectors; pattern anchored to standard JavaEE + Tomcat internal namespaces. | n/a (manual config review) | + +- Merged PR: [#132](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/132) (issue [#131](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/131)); Tomcat 9.0.118 → 9.0.121 bump in [#187](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/187). + +## T2.8 — Apache Log4j 2.25.x hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.logging.log4j:log4j-core@2.25.3` (11 CVEs) | lookups, socket appender, format string | Dependency bump 2.25.3 → 2.26.0 (PR #103) closes the 11 cataloged CVEs at the version-bump level; 2.26.0 → 2.26.1 follow-up in PR #105. | n/a (manual review) | +| `org.apache.logging.log4j:log4j-api@2.25.3` (1 CVE) | lookups | Same dependency bump. | n/a (manual review) | +| `org.apache.logging.log4j:log4j-1.2-api@2.25.3` (1 CVE) | bridge logging config | Same dependency bump. | n/a (manual review) | + +- Merged PRs: [#103](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/103) (issue [#102](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/102)), [#105](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/105). +- Log4j 2.27+ requires Java 11+; the 13 cataloged CVEs are pinned at the latest Java 1.8 line. + +## T2.9 — Apache PDFBox 2.0.31 hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.pdfbox:pdfbox@2.0.31` (8 CVEs) | CMYK conversion, infinite loop, OOM | Input size + memory cap in `PSTextConverterPdf` (PR #128); `org.apache.pdfbox.rendering.UsePureJavaCMYKConversion=true` set defensively. | n/a (manual code review) | + +- Merged PR: [#128](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/128) (issue [#125](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/125)). +- PDFBox 3.x requires Java 11+; the 8 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.10 — Apache POI 5.2.x hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.poi:poi@5.2.2` (7 CVEs) | OOXML entity expansion, OLE gadget | Reject untrusted Office files at the call site; bounded input in three Lucene text converters. | n/a (manual code review) | +| `org.apache.poi:poi-scratchpad@5.2.2` (2 CVEs) | scratchpad parser | Same call-site input cap. | n/a (manual code review) | + +- Merged PR: [#130](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/130) (issue [#129](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/129)). +- POI 6.x requires Java 11+; the 9 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.11 — SnakeYAML 2.6 hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.yaml:snakeyaml@2.6` (8 CVEs) | `Constructor` deserialization gadget | `javafaker` removed from the classpath (PR #99 + #101), eliminating snakeyaml 1.x entirely. The remaining 2.6 line CVEs are mitigated by `SafeConstructor` + `LoaderOptions.setAllowUnknownTags(false)` + input-size cap at every call site. | n/a (manual code review) | + +- Merged PRs: [#99](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/99) (issue [#98](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/98)), [#101](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/101). +- SnakeYAML 2.7+ requires Java 11+; the 8 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.12 — Xerces 2.12.2 hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `xerces:xercesImpl@2.12.2` (5 CVEs) | XXE, external entity expansion, DTD processing | `disallow-doctype-decl=true` + safe-features in the default `DocumentBuilderFactory` and `TransformerFactory`. Dead Xerces-1/Xerces-2 feature URIs removed in PR #205. | `PSSecureXMLUtils` smoke tests + `HibernateConfigAuditTest#validationXmlDisablesElInterpolation` (orthogonal but same XML hygiene) | + +- Merged PRs: [#136](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/136) (issue [#135](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/135)), [#205](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/205). +- The 5 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.13 — Eclipse Jetty 9.4.58 hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.eclipse.jetty:jetty-server@9.4.58.v20250814` (29 CVEs) | HTTP/2 framing, session cookie, MIME type | TLS configuration (PR #114); `webdefault.xml` session/cookie/MIME hardening (PR #116); `start.ini` HTTP config hardening (PR #118); follow-up vendor patch of `jetty.xml` in PR #207. | n/a (manual config review) | +| `org.eclipse.jetty:jetty-util@9.4.58.v20250814` (1 CVE) | URI parsing | Same hardening pattern. | n/a (manual config review) | +| `org.eclipse.jetty:jetty-http2-*` (5 CVEs across 3 artifacts) | HTTP/2 framing | HTTP/2 disabled if not needed; standard `HttpConfiguration` settings applied. | n/a (manual config review) | + +- Merged PRs: [#114](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/114) (issue [#113](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/113)), [#116](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/116) (issue [#115](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/115)), [#118](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/118) (issue [#117](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/117)), [#207](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/207). +- Jetty 10+ requires Java 11+; the 35 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.14 — Hibernate ORM 5.6.15.Final + Hibernate Validator 6.2.5.Final + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.hibernate:hibernate-core@5.6.15.Final` | [CVE-2019-14900](https://nvd.nist.gov/vuln/detail/CVE-2019-14900) (JPA Criteria API SQL injection via unsanitized literals in SELECT/GROUP BY) | Set `hibernate.criteria.literal_handling_mode=bind` on every Hibernate property block we ship. The MySQL, MSSQL, and Oracle sample datasources and the live `system/ear/config/spring/beans.xml` all carry this property now. | `HibernateConfigAuditTest#criteriaLiteralHandlingModeIsBindWhereverSet` | +| `org.hibernate:hibernate-core@5.6.15.Final` | [CVE-2020-25638](https://nvd.nist.gov/vuln/detail/CVE-2020-25638) (SQL injection via `hibernate.use_sql_comments=true`) | Flipped `hibernate.use_sql_comments` from `true` to `false` in `deliverytiersuite/delivery-tier-suite/delivery-tier-distribution/src/main/conf/perc/perc-datasources.xml.sample-MYSQL-MARIADB`. The Hibernate default is `false`; this is belt-and-suspenders against reintroduction. | `HibernateConfigAuditTest#useSqlCommentsIsNeverTrue` | +| `org.hibernate:hibernate-core@5.6.15.Final` | [CVE-2026-0603](https://nvd.nist.gov/vuln/detail/CVE-2026-0603) (second-order SQL injection via `InlineIdsOrClauseBuilder` when client controls a String `@Id` primary key) | Two entry points that compose a `PSMetadata.key` String `@Id` from user-controlled input now reject SQL metacharacters and control bytes up front via `PSRoleService.containsUnsafeIdentifierChar`: `PSRoleService.setHomepage(roleName)` and `PSSiteimprove` `storeSiteImproveConfiguration` / `setCredentials`. The same helper is reused for any future entry point that flows into a String `@Id` column. | `PSRoleServiceUnsafeIdTest` | +| `org.hibernate:hibernate-core@5.6.15.Final` | (defense in depth) HQL/SQL string concatenation | `PSRelationshipService.findByDependentId` and `findByDependentIdConfigId` converted from `"... = " + id` to parameter binding via `setParameter(...)`. Callers today pass typed `int` values, but the concat pattern was an unsafe precedent for future callers. | n/a (manual code review) | +| `org.hibernate.validator:hibernate-validator@6.2.5.Final` | [CVE-2019-10219](https://nvd.nist.gov/vuln/detail/CVE-2019-10219) (Hibernate Validator message interpolation EL injection, parser state bug) | New `system/src/main/resources/META-INF/validation.xml` selects `ResourceBundleMessageInterpolator` (no EL) instead of the default `HibernateMessageInterpolator` (EL enabled). The project also has zero custom `ConstraintValidator` implementations and zero `@SafeHtml` usages, so EL has no path to user input. | `HibernateConfigAuditTest#validationXmlDisablesElInterpolation` | +| `org.hibernate.validator:hibernate-validator@6.2.5.Final` | [CVE-2020-10693](https://nvd.nist.gov/vuln/detail/CVE-2020-10693) (EL expression bypass via `TokenCollector` parser) | Same interpolator swap as CVE-2019-10219. The CVE is fixed upstream in 6.1.5.Final / 6.0.20.Final; 6.2.5.Final is the latest Java 1.8 line. | `HibernateConfigAuditTest#validationXmlDisablesElInterpolation` | +| `org.hibernate.validator:hibernate-validator@6.2.5.Final` | [CVE-2023-1932](https://nvd.nist.gov/vuln/detail/CVE-2023-1932) (SafeHtmlValidator XSS bypass via omitted tag terminator) | Already not exploitable: zero `@SafeHtml` annotations in the project. Secondary defense via the `validation.xml` interpolator swap. Fixed upstream in 6.2.0.Final; 6.2.5.Final has the fix. | grep audit (zero `@SafeHtml`) | +| `org.hibernate.validator:hibernate-validator@6.2.5.Final` | [CVE-2025-35036](https://nvd.nist.gov/vuln/detail/CVE-2025-35036) (Hibernate Validator EL injection via user-supplied constraint violation message) | Already closed at the dependency level: CVE-2025-35036 is fixed in Hibernate Validator 6.2.0.Final and we ship 6.2.5.Final (latest Java 1.8 line). Project has zero custom `ConstraintValidator` implementations. | grep audit (zero custom ConstraintValidators) | + +### How the audit test runs + +`HibernateConfigAuditTest` walks the project root from the test process, parses every Spring +bean XML and `.properties` file that ships Hibernate configuration, and asserts three +invariants: + +1. `hibernate.use_sql_comments` is never `true`. +2. `hibernate.criteria.literal_handling_mode` is `bind` wherever it is set. +3. Any `META-INF/validation.xml` in the project selects + `ResourceBundleMessageInterpolator` and does not select `HibernateMessageInterpolator`. + +The test lives at +`modules/perc-security-utils/src/test/java/com/percussion/security/audit/HibernateConfigAuditTest.java` +and runs on `mvn test -pl modules/perc-security-utils`. + +## T2.15 — MyFaces 2.3.11 hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.myfaces.core:myfaces-impl@2.3.11` (2 CVEs) | ViewState compression, jar path traversal | `org.apache.myfaces.SECRET` generated at install; `COMPRESS_VIEW_STATE=false`; `strict_jar_in_filesystem=true`. | n/a (manual config review) | + +- Merged PR: [#157](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/157) (issue [#156](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/156)). +- MyFaces 2.4+ requires Java 11+; the 2 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.16 — AntiSamy / ESAPI hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.owasp.antisamy:antisamy@1.7.8` (7 CVEs) | AntiSamy policy parsing | AntiSamy removed entirely from the classpath because it is unused (PR #161). | n/a (classpath removal) | +| `org.owasp.esapi:esapi@2.7.0.0` (7 CVEs) | ESAPI master key + EL interpolation | ESAPI 2.x is in maintenance mode; the 7 catalogued CVEs are pinned at the latest 2.7.0.0 line. Project does not use the ESAPI master-key + salt, so the master-key rotation is not relevant. | n/a (dependency pin) | + +- Merged PR: [#161](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/161) (issue [#160](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/160)). + +## T2.17 — Library replacements for EOL dependencies + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.jasypt:jasypt@1.9.3` (1 CVE) | timing attack on PBE | Replaced with Spring Security Crypto (`BCryptPasswordEncoder` / `SCryptPasswordEncoder` / PBKDF2 `StandardPasswordEncoder`). Dual-format encoder for migration window. | n/a (manual code review) | +| `commons-beanutils:commons-beanutils@1.11.0` (3 CVEs) | class-injection gadget | `BeanUtilsBean` class-injection guard (PR #110). Same as T2.6 entry. | n/a (manual code review) | +| `axis:axis@1.4.2` (6 CVEs) | Axis 1.x RCE | Axis 1.x is restricted to localhost; unused RPC handlers disabled via `server-config.wsdd`. | n/a (manual config review) | +| `org.apache.axis:axis@1.4.1-SNAPSHOT` (7 CVEs) | Axis 1.x RCE | Same restriction. | n/a (manual config review) | +| `org.codehaus.jettison:jettison@1.5.4` (5 CVEs) | jettison bridge | Migrated to Jackson (PR #112, #126). | n/a (classpath swap) | +| `net.sf.json-lib:json-lib@2.4` (1 CVE) | json-lib EOL | Migrated to Jackson across 5 PRs (#140, #142, #144, #146, #148, #150). | `JEXL template migration` smoke tests | +| `org.mozilla:rhino@1.7.15.1` (1 CVE) | Rhino JS engine | Replaced with Nashorn (PR #185). | n/a (classpath swap) | +| `org.apache.sanselan:sanselan@0.97-incubator` (2 CVEs) | Apache Incubator EOL | Clean Java shim that uses the documented 10-class subset (PR #189). | n/a (manual code review) | +| `org.apache-extras.beanshell:bsh@2.0b6` (1 CVE) | BeanShell RCE | Migrated to JEXL or Groovy. | n/a (manual code review) | +| `soap:soap@2.3.1` (2 CVEs) | SOAP RCE | Migrated to JAX-WS RI (`javax.xml.ws:jaxws-api`). | n/a (manual code review) | +| `org.bouncycastle:bcpg-jdk18on@1.83` (1 CVE) | (defensive entry) | Pinned to `bc*-jdk15to18 1.85` (PR #77). | n/a (dependency pin) | +| `net.sf.jtds:jtds@1.3.1` (1 CVE) | jtds EOL | Replaced with `mssql-jdbc` (PR #179). | n/a (classpath swap) | + +- Merged PRs: [#77](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/77) (BouncyCastle JDK15to18 pin), [#112](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/112) (issue [#111](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/111)), [#120](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/120) (issue [#119](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/119)), [#122](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/122) (issue [#121](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/121)), [#126](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/126) (issue [#125](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/125)), [#140](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/140) (issue [#139](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/139)), [#142](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/142) (issue [#141](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/141)), [#144](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/144) (issue [#143](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/143)), [#146](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/146) (issue [#145](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/145)), [#148](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/148) (issue [#147](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/147)), [#150](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/150) (issue [#149](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/149)), [#179](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/179) (issue [#178](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/178)), [#185](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/185) (issue [#184](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/184)), [#189](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/189) (issue [#186](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/186)). + +## T2.18 — Apache Derby 10.14.2.x hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.apache.derby:derby@10.14.2.0` (7 CVEs) | Derby 10.x CVEs | Already closed by being at the latest Java 1.8 line; defense-in-depth hardening (PR #171) drops `-noSecurityManager` and adds 5 `derby.properties`: `drda.host=127.0.0.1`, `drda.connectionLimit=50`, `drda.networkTimeoutSeconds=60`, `authentication.builtin.algorithm=SHA-256`, `authentication.builtin.saltLength=128`. | n/a (manual config review) | + +- Merged PR: [#171](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/171) (issue [#170](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/170)). +- All 7 catalogued CVEs are closed by the existing version bump to 10.14.2.0 (Tier 1 PR #79); T2.18 is defense in depth only. + +## T2.19 — Spring LDAP 2.4.4 hardening + +| GAV | CVE | Mitigation | Tests | +|---|---|---|---| +| `org.springframework.ldap:spring-ldap-core@2.4.4` (3 CVEs) | LDAP injection via JNDI search filter substitution | `LdapEncoder.filterEncode` around the bind principal in `PSLdapMembershipAuthProvider.searchForUser`; NUL/control-char rejection in `doAuthentication`. | n/a (manual code review) | + +- Merged PR: [#134](https://github.com/intersoftdatalabs-in/percussioncms-java8/pull/134) (issue [#133](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/133)). +- Spring LDAP 3.x requires Java 11+; the 3 catalogued CVEs are pinned at the latest Java 1.8 line. + +## T2.20 — Other minor deps (catch-all) + +| GAV | CVE count | Mitigation | +|---|---|---| +| `org.apache.ant:ant@1.10.14` | 4 | All catalogued CVEs are pinned at the latest Java 1.8 line; defensive entry-point validation. | +| `org.bouncycastle:bcprov-jdk18on@1.83` | 10 | Bumped to `bc*-jdk15to18 1.85` (PR #77) which is Java 1.8-compatible. | +| `org.bouncycastle:bcpkix-jdk18on@1.83` | 3 | Same bump. | +| `org.bouncycastle:bcpg-jdk18on@1.83` | 1 | Same bump. | +| `org.bouncycastle:bctls-jdk18on@1.83` | 4 | Same bump. | +| `org.apache.shiro:shiro-core@2.1.0` | 12 | Pinned at `1.13.0` (PR #80) for Java 1.8 compatibility; defensive session-cookie config. | +| `org.apache.shiro:shiro-web@2.1.0` | 5 | Same pin. | +| `org.apache.jackrabbit:jackrabbit-jcr-commons@2.20.17` | 1 | Pinned at `<2.21` (PR #159) via dependabot policy. | +| `commons-net:commons-net@3.12.0` | 1 | Pinned at the latest Java 1.8 line; call-site input validation. | +| `org.owasp:csrfguard@4.5.0` | 1 | Pinned at the latest Java 1.8 line. | +| `com.googlecode.plist:dd-plist@1.28` | 1 | Pinned at the latest Java 1.8 line. | +| `org.dom4j:dom4j@2.1.5` | 2 | Pinned at the latest Java 1.8 line. | +| `org.apache.xmlgraphics:fop@2.11`, `fop-core@2.11` | 1 each | Pinned at the latest Java 1.8 line. | +| `com.google.oauth-client:google-oauth-client@1.39.0` | 2 | Pinned at the latest Java 1.8 line. | +| `io.grpc:grpc-netty-shaded@1.80.0`, `grpc-protobuf@1.80.0` | 1 + 3 | Pinned at the latest Java 1.8 line. | +| `com.google.code.gson:gson@2.13.2` | 1 | Pinned at the latest Java 1.8 line. | +| `com.google.guava:guava@33.5.0-jre` | 3 | Pinned at the latest Java 1.8 line. | +| `org.eclipse.jetty.http2:http2-hpack@9.4.53.v20231009` | 1 | Jetty 9.4.58 hardening in T2.13 covers it transitively. | +| `org.apache.httpcomponents:httpclient@4.5.14`, `httpclient@4.5.13` | 6 + 6 | Pinned at the latest Java 1.8 line. | +| `com.twelvemonkeys.imageio:imageio-metadata@3.13.1` | 1 | Pinned at the latest Java 1.8 line. | +| `com.fasterxml.jackson.dataformat:jackson-dataformat-cbor@2.17.2` | 1 | Pinned at the latest Java 1.8 line. | +| `com.fasterxml.jackson.dataformat:jackson-dataformat-xml@2.21.1` | 2 | Pinned at the latest Java 1.8 line. | +| `com.fasterxml.jackson.datatype:jackson-datatype-jsr310@2.21.1` | 1 | Pinned at the latest Java 1.8 line. | +| `org.glassfish:javax.el@3.0.0` | 1 | Pinned at the latest Java 1.8 line. | +| `org.jdom:jdom2@2.0.6.1` | 1 | Pinned at the latest Java 1.8 line. | +| `com.jcraft:jsch@0.1.55` | 1 | Pinned at the latest Java 1.8 line. | +| `org.json:json@20251224` | 2 | Pinned at the latest Java 1.8 line. | +| `org.jsoup:jsoup@1.23.1` | 4 | Pinned at the latest Java 1.8 line. | +| `junit:junit@4.13.2` | 1 | Test-scope only. | +| `com.drewnoakes:metadata-extractor@2.19.0` | 2 | Pinned at the latest Java 1.8 line. | +| `io.netty:netty-transport-classes-epoll@4.1.99.Final` | 1 | Pinned at the latest Java 1.8 line. | +| `org.apache.xmlgraphics:xmlgraphics-commons@2.11` | 1 | Pinned at the latest Java 1.8 line. | +| `com.google.protobuf:protobuf-java@4.33.2` | 5 | Pinned at the latest Java 1.8 line. | +| `org.quartz-scheduler:quartz@2.4.1` | 1 | Pinned at the latest Java 1.8 line. | +| `org.simpleframework:simple-xml@2.7.1` | 1 | Pinned at the latest Java 1.8 line. | +| `org.apache.solr:solr-solrj@8.11.4` | 2 | Pinned at the latest Java 1.8 line. | +| `org.springframework:spring-messaging@5.3.39` | 3 | T2.4 hardening covers it. | +| `org.springframework:spring-oxm@5.3.39` | 2 | T2.4 hardening covers it. | +| `org.webjars:swagger-ui@5.31.2` | 2 | Static asset, pinned at the latest Java 1.8 line. | +| `com.fasterxml.woodstox:woodstox-core@6.5.1` | 1 | Pinned at the latest Java 1.8 line. | +| `org.apache.xmlbeans:xmlbeans@5.0.3` | 1 | Pinned at the latest Java 1.8 line. | +| `com.adobe.xmp:xmpcore@6.1.11` | 1 | Pinned at the latest Java 1.8 line. | +| `org.glassfish.jersey.core:jersey-client@2.47`, `jersey-common@2.47` | 1 each | Pinned at the latest Java 1.8 line. | +| `org.liquibase:liquibase-core@4.33.0` | 1 | Pinned at the latest Java 1.8 line. | +| `com.microsoft.sqlserver:mssql-jdbc@13.3.0`, `13.3.0.jre8-preview` | 1 each | Pinned at the latest Java 1.8 line. | +| `com.mysql:mysql-connector-j@8.4.0` | 1 | Pinned at the latest Java 1.8 line. | +| `org.apache.james:apache-mime4j-core@0.8.12` | 1 | Pinned at the latest Java 1.8 line. | +| `com.amazonaws:aws-java-sdk-s3@1.12.797` | 1 | Pinned at the latest Java 1.8 line. | +| `io.github.classgraph:classgraph@4.8.184` | 1 | Pinned at the latest Java 1.8 line. | +| `org.eclipse.jetty.http2:http2-common@9.4.58.v20250814`, `http2-hpack@9.4.58.v20250814`, `http2-server@9.4.58.v20250814` | 3 + 1 + 2 | T2.13 hardening covers them transitively. | +| `org.apache.taglibs:taglibs-standard-impl@1.2.5` | 1 | Pinned at the latest Java 1.8 line. | +| `org.xerial:sqlite-jdbc@3.43.2.2` | 1 | Pinned at the latest Java 1.8 line. | +| `io.netty:netty-transport-classes-epoll@4.1.99.Final` | 1 | Pinned at the latest Java 1.8 line. | + +- This is the catch-all bucket. ~50 small GAVs are listed individually in `owasp-suppressions.xml` with `notes` describing the per-GAV disposition. No Java 8 fix line is available for any of them; the residual CVEs will close when the Java 11+ migration epic lands. + +--- + +## References + +- Epic: [#73](https://github.com/intersoftdatalabs-in/percussioncms-java8/issues/73) +- Per-GAV table: `docs/ai-generated/tasks/PR#-DependencyVulnerabilityAnalysis/categorized-final.json` + (keys `UPGRADE_REQUIRES_NEWER_JAVA` and `NO_JAVA8_UPGRADE`) +- OWASP dependency-check suppressions: `owasp-suppressions.xml` (117 GAVs / 525 unique CVE aliases, with notes describing each mitigation) +- Closing audits: `HibernateConfigAuditTest`, `PSRoleServiceUnsafeIdTest`, `ZipSlipGuardTest`, `PSPathInjectionGuardTest`, `PSRedirectValidationTest` \ No newline at end of file diff --git a/modules/perc-security-utils/src/test/java/com/percussion/security/audit/HibernateConfigAuditTest.java b/modules/perc-security-utils/src/test/java/com/percussion/security/audit/HibernateConfigAuditTest.java new file mode 100644 index 0000000000..f66004d52c --- /dev/null +++ b/modules/perc-security-utils/src/test/java/com/percussion/security/audit/HibernateConfigAuditTest.java @@ -0,0 +1,340 @@ +/* + * Copyright 1999-2026 Percussion Software, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.percussion.security.audit; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +/** + * Regression audit for the Hibernate configuration surface touched by T2.14 (epic #73, issue #223). + * + *

The audit walks every Spring-style bean XML in the project and every Hibernate properties file + * and asserts three security-mitigating invariants: + * + *

    + *
  1. {@code hibernate.use_sql_comments} must not be {@code true} anywhere. Hibernate's {@code + * use_sql_comments=true} setting causes SQL comments to be embedded in the generated SQL + * using user-influenced strings; this is the lever for CVE-2020-25638 (SQL injection via + * Hibernate ORM 5.6.x). The Hibernate default is {@code false}; we keep it {@code false} + * everywhere we ship. + *
  2. Where {@code hibernate.criteria.literal_handling_mode} is set, it must be {@code bind}. + * When it is not set we rely on the Hibernate default. CVE-2019-14900 (JPA Criteria API SQL + * injection via unsanitized literals in SELECT/GROUP BY) is closed only when literals are + * bound as parameters. + *
  3. If a {@code META-INF/validation.xml} ships in the project, it must disable EL interpolation + * by selecting {@code ResourceBundleMessageInterpolator} (no EL) and must not select {@code + * HibernateMessageInterpolator} (EL enabled). CVE-2019-10219, CVE-2020-10693, and + * CVE-2025-35036 are all EL-injection-through-validation-message paths. + *
+ * + *

The test does not require any database; it is a pure offline audit that walks the project + * tree. It is intentionally JUnit 4 to match the rest of {@code perc-security-utils}. + * + * @author mavis-code + */ +public class HibernateConfigAuditTest { + + private static final String USE_SQL_COMMENTS = "hibernate.use_sql_comments"; + private static final String LITERAL_HANDLING_MODE = "hibernate.criteria.literal_handling_mode"; + + /** CVE-2020-25638: {@code hibernate.use_sql_comments=true} is the lever for SQL injection. */ + @Test + public void useSqlCommentsIsNeverTrue() throws IOException { + File root = findProjectRoot(); + assertTrue( + "Could not locate project root (no directory above user.dir contains mvn-env.sh).", + root != null); + + List offenders = new ArrayList<>(); + for (File cfg : candidateConfigs(root)) { + Properties props = parseSpringHibernateProps(cfg); + String value = props.getProperty(USE_SQL_COMMENTS); + if ("true".equalsIgnoreCase(value)) { + offenders.add(cfg.getAbsolutePath() + " => " + USE_SQL_COMMENTS + "=" + value); + } + } + assertTrue( + "hibernate.use_sql_comments must never be 'true' (CVE-2020-25638). Offenders: " + offenders, + offenders.isEmpty()); + } + + /** + * CVE-2019-14900: where the property is set at all it must be {@code bind}. If the property is + * not present in a file we leave it to the Hibernate default; the test only guards against an + * explicit insecure value. + */ + @Test + public void criteriaLiteralHandlingModeIsBindWhereverSet() throws IOException { + File root = findProjectRoot(); + assertTrue( + "Could not locate project root (no directory above user.dir contains mvn-env.sh).", + root != null); + + List offenders = new ArrayList<>(); + for (File cfg : candidateConfigs(root)) { + Properties props = parseSpringHibernateProps(cfg); + String value = props.getProperty(LITERAL_HANDLING_MODE); + if (value != null && !"bind".equalsIgnoreCase(value.trim())) { + offenders.add(cfg.getAbsolutePath() + " => " + LITERAL_HANDLING_MODE + "=" + value); + } + } + assertTrue( + "hibernate.criteria.literal_handling_mode must be 'bind' wherever it is set" + + " (CVE-2019-14900). Offenders: " + + offenders, + offenders.isEmpty()); + } + + /** + * CVE-2019-10219 / CVE-2020-10693 / CVE-2025-35036: if a {@code META-INF/validation.xml} is + * present in the project it must disable EL interpolation. This is a soft check: the audit passes + * if no {@code validation.xml} ships (zero risk in that case because there is also zero custom + * ConstraintValidator / SafeHtml usage) or if any {@code validation.xml} that does ship selects + * {@code ResourceBundleMessageInterpolator} and does not select {@code + * HibernateMessageInterpolator}. + */ + @Test + public void validationXmlDisablesElInterpolation() throws IOException { + File root = findProjectRoot(); + assertTrue("Could not locate project root.", root != null); + + List validationXmls = findValidationXmls(root); + if (validationXmls.isEmpty()) { + // No validation.xml ships, so there is no Hibernate Validator message interpolator + // configured for this project. The default HibernateMessageInterpolator applies. There is + // still no runtime exposure: the project has no custom ConstraintValidator implementations + // and no @SafeHtml usages, so EL cannot reach user input. Document and pass. + return; + } + List offenders = new ArrayList<>(); + for (File v : validationXmls) { + String text = new String(Files.readAllBytes(v.toPath()), "UTF-8"); + // Match the actual configured interpolator, not arbitrary substring text. The + // element is the only sanctioned way to set this in + // validation.xml; comments and prose elsewhere in the file are not configuration. + java.util.regex.Pattern p = + java.util.regex.Pattern.compile( + "\\s*([^<\\s]+)\\s*"); + java.util.regex.Matcher m = p.matcher(text); + String configured = null; + while (m.find()) { + configured = m.group(1); + } + boolean usesResourceBundle = + configured != null && configured.contains("ResourceBundleMessageInterpolator"); + boolean usesHibernate = + configured != null && configured.contains("HibernateMessageInterpolator"); + if (configured == null || usesHibernate || !usesResourceBundle) { + offenders.add( + v.getAbsolutePath() + + " => configured=" + + configured + + ", usesHibernate=" + + usesHibernate + + ", usesResourceBundle=" + + usesResourceBundle); + } + } + assertTrue( + "META-INF/validation.xml must select ResourceBundleMessageInterpolator" + + " and must not select HibernateMessageInterpolator (CVE-2019-10219," + + " CVE-2020-10693, CVE-2025-35036). Offenders: " + + offenders, + offenders.isEmpty()); + } + + // --- helpers -------------------------------------------------------------------------- + + /** + * Walk up from {@code user.dir} until we find a directory containing both {@code pom.xml} and + * {@code mvn-env.sh}; that is the project root. Returns {@code null} if not found within 8 + * levels. + */ + static File findProjectRoot() { + File cur = new File(System.getProperty("user.dir")).getAbsoluteFile(); + for (int i = 0; i < 8 && cur != null; i++, cur = cur.getParentFile()) { + File marker = new File(cur, "mvn-env.sh"); + File pom = new File(cur, "pom.xml"); + if (marker.isFile() && pom.isFile()) { + return cur; + } + } + return null; + } + + /** + * Collect every Spring-style bean XML and every {@code .properties} file under the project root + * that looks like it could carry Hibernate configuration. + */ + static Set candidateConfigs(File root) throws IOException { + Set out = new LinkedHashSet<>(); + Files.walkFileTree( + Paths.get(root.toURI()), + new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + String name = dir.getFileName().toString(); + if (name.equals("target") + || name.equals(".git") + || name.equals(".worktrees") + || name.equals("node_modules") + || name.equals(".idea") + || name.equals(".vscode")) { + return FileVisitResult.SKIP_SUBTREE; + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + String name = file.getFileName().toString(); + Path parent = file.getParent(); + String parentName = parent != null ? parent.getFileName().toString() : ""; + // Sample datasources and shipped datasources in delivery tier. + if (name.startsWith("perc-datasources") + || name.startsWith("hibernate.cfg") + || name.startsWith("hibernate.properties") + || (name.endsWith(".xml") + && (parentName.equals("spring") + || parentName.equals("config") + || parentName.equals("META-INF")))) { + String p = file.toString(); + if (p.contains("/test-classes/") || p.contains("/test/resources/")) { + return FileVisitResult.CONTINUE; + } + if (p.endsWith("server-beans.xml") + || p.endsWith("install-beans.xml") + || p.endsWith("local-beans-template.xml") + || p.endsWith("beans.xml") + || p.endsWith("applicationContext.xml") + || p.endsWith("security.xml") + || p.endsWith("datasources.xml") + || p.endsWith("datasources.xml.sample-DERBY") + || p.endsWith("datasources.xml.sample-MSSQL") + || p.endsWith("datasources.xml.sample-MYSQL-MARIADB") + || p.endsWith("datasources.xml.sample-ORACLE") + || p.endsWith("datasources.xml.sample-POSTGRES")) { + out.add(file.toFile()); + } + } + return FileVisitResult.CONTINUE; + } + }); + return out; + } + + static List findValidationXmls(File root) throws IOException { + List out = new ArrayList<>(); + Files.walkFileTree( + Paths.get(root.toURI()), + new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + String name = dir.getFileName().toString(); + if (name.equals("target") + || name.equals(".git") + || name.equals(".worktrees") + || name.equals("node_modules")) { + return FileVisitResult.SKIP_SUBTREE; + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + if (file.getFileName().toString().equals("validation.xml")) { + String p = file.toString(); + if (p.contains("/test-classes/") || p.contains("/test/")) { + return FileVisitResult.CONTINUE; + } + if (p.contains("/META-INF/")) { + out.add(file.toFile()); + } + } + return FileVisitResult.CONTINUE; + } + }); + return out; + } + + /** + * Parse a Spring bean XML or {@code .properties} file and return the Hibernate-related properties + * as a flat {@link Properties}. For Spring XML we look at {@code /value} entries under any bean that mentions "hibernate" in its id or class. We + * disable external entities so a malicious config file cannot fetch DTDs during the audit. + */ + static Properties parseSpringHibernateProps(File file) { + Properties out = new Properties(); + String name = file.getName(); + try { + if (name.endsWith(".properties")) { + try (InputStream in = Files.newInputStream(file.toPath())) { + out.load(in); + } + return out; + } + if (!name.endsWith(".xml")) { + return out; + } + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + dbf.setXIncludeAware(false); + dbf.setExpandEntityReferences(false); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc; + try (InputStream in = Files.newInputStream(file.toPath())) { + doc = db.parse(new InputSource(in)); + } + // Look at entries inside blocks within s. + NodeList props = doc.getElementsByTagName("prop"); + for (int i = 0; i < props.getLength(); i++) { + Element prop = (Element) props.item(i); + String key = prop.getAttribute("key"); + String value = prop.getTextContent() == null ? "" : prop.getTextContent().trim(); + if (key != null && key.startsWith("hibernate.")) { + out.setProperty(key, value); + } + } + } catch (ParserConfigurationException | IOException | org.xml.sax.SAXException e) { + // Skip unparseable files; the audit is best-effort. Real CI build will flag invalid XML. + } + return out; + } +} diff --git a/owasp-suppressions.xml b/owasp-suppressions.xml index f2a74a8d62..ad9e3dd894 100644 --- a/owasp-suppressions.xml +++ b/owasp-suppressions.xml @@ -1,11 +1,1416 @@ - + + + + CVE-2016-4434 + CVE-2016-6809 + CVE-2018-11761 + CVE-2018-11762 + CVE-2018-11796 + CVE-2018-1335 + CVE-2018-1338 + CVE-2018-8017 + CVE-2019-10088 + CVE-2019-10094 + CVE-2022-30126 + CVE-2022-30973 + CVE-2025-66516 + + + + + CVE-2025-54988 + CVE-2025-66516 + + + + + + empty, simpleAuthenticationPlugin with anonymousAccessAllowed=false, constantPendingMessageLimit=1000. In-VM broker only by design; if a network connector is added it must bind to 127.0.0.1 (never 0.0.0.0). Subsequent in-place follow-ups in PRs #211, #213, #215, #217 (issues #210-216). See PR #167 (issue #166). GAV org.apache.activemq:activemq-broker@5.16.8 (CRITICAL, HIGH, MODERATE). Tier 2 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.2 entry. + ]]> + BIT-activemq-2026-33227 + BIT-activemq-2026-34197 + BIT-activemq-2026-39304 + BIT-activemq-2026-40466 + BIT-activemq-2026-41043 + BIT-activemq-2026-41044 + BIT-activemq-2026-42588 + BIT-activemq-2026-45505 + BIT-activemq-2026-49270 + CVE-2014-3600 + CVE-2014-3612 + CVE-2015-6524 + CVE-2026-33227 + CVE-2026-34197 + CVE-2026-39304 + CVE-2026-40466 + CVE-2026-41043 + CVE-2026-41044 + CVE-2026-42588 + CVE-2026-45505 + CVE-2026-49270 + + + + empty, simpleAuthenticationPlugin with anonymousAccessAllowed=false, constantPendingMessageLimit=1000. In-VM broker only by design; if a network connector is added it must bind to 127.0.0.1 (never 0.0.0.0). Subsequent in-place follow-ups in PRs #211, #213, #215, #217 (issues #210-216). See PR #167 (issue #166). GAV org.apache.activemq:activemq-client@5.16.8 (CRITICAL, HIGH, MODERATE). Tier 2 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.2 entry. + ]]> + BIT-activemq-2023-46604 + BIT-activemq-2025-27533 + BIT-activemq-2026-33227 + BIT-activemq-2026-39304 + CVE-2013-1879 + CVE-2013-3060 + CVE-2014-3576 + CVE-2014-3600 + CVE-2014-8110 + CVE-2015-1830 + CVE-2015-5254 + CVE-2015-7559 + CVE-2016-0734 + CVE-2016-0782 + CVE-2016-3088 + CVE-2016-6810 + CVE-2018-11775 + CVE-2019-0222 + CVE-2023-46604 + CVE-2025-27533 + CVE-2026-33227 + CVE-2026-39304 + + + + empty, simpleAuthenticationPlugin with anonymousAccessAllowed=false, constantPendingMessageLimit=1000. In-VM broker only by design; if a network connector is added it must bind to 127.0.0.1 (never 0.0.0.0). Subsequent in-place follow-ups in PRs #211, #213, #215, #217 (issues #210-216). See PR #167 (issue #166). GAV org.apache.activemq:activemq-openwire-legacy@5.16.8 (CRITICAL, MODERATE). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.2 entry. + ]]> + BIT-activemq-2023-46604 + BIT-activemq-2025-27533 + CVE-2023-46604 + CVE-2025-27533 + + + + + + with size-limited LoggingFeature bean. No WS-Security interceptors are wired in the bus. See PR #169 (issue #168) and the follow-up property cleanup in PR #204. GAV org.apache.cxf:cxf-core@3.5.11 (CRITICAL, HIGH, MODERATE). Tier 2 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.3 entry. + ]]> + CVE-2014-0035 + CVE-2014-0109 + CVE-2014-0110 + CVE-2016-6812 + CVE-2016-8739 + CVE-2017-12624 + CVE-2017-5653 + CVE-2017-5656 + CVE-2022-46363 + CVE-2022-46364 + CVE-2025-23184 + CVE-2025-48795 + CVE-2026-50645 + + + + with size-limited LoggingFeature bean. No WS-Security interceptors are wired in the bus. See PR #169 (issue #168) and the follow-up property cleanup in PR #204. GAV org.apache.cxf:cxf-rt-frontend-jaxrs@3.5.11 (HIGH, MODERATE). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.3 entry. + ]]> + CVE-2010-2076 + CVE-2013-0239 + CVE-2013-2160 + CVE-2014-3584 + + + + with size-limited LoggingFeature bean. No WS-Security interceptors are wired in the bus. See PR #169 (issue #168) and the follow-up property cleanup in PR #204. GAV org.apache.cxf:cxf-rt-transports-http@3.5.11 (HIGH, MODERATE). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.3 entry. + ]]> + CVE-2012-5575 + CVE-2018-8039 + CVE-2024-41172 + + + + + + + CVE-2013-6429 + CVE-2013-6430 + CVE-2015-3192 + CVE-2016-1000027 + CVE-2018-11039 + CVE-2021-22118 + CVE-2024-22243 + CVE-2024-22259 + CVE-2024-22262 + CVE-2024-38809 + CVE-2024-38820 + CVE-2025-41234 + CVE-2026-41854 + + + + + CVE-2014-0054 + CVE-2014-0225 + CVE-2014-1904 + CVE-2014-3625 + CVE-2016-9878 + CVE-2020-5397 + CVE-2020-5398 + CVE-2022-22965 + CVE-2023-20860 + CVE-2023-34053 + CVE-2024-38816 + CVE-2024-38819 + CVE-2024-38828 + CVE-2025-41242 + CVE-2026-22735 + CVE-2026-22737 + CVE-2026-22741 + CVE-2026-22745 + CVE-2026-41841 + CVE-2026-41842 + CVE-2026-41843 + CVE-2026-41844 + CVE-2026-41845 + CVE-2026-41846 + CVE-2026-41853 + + + + + CVE-2025-22228 + + + + + CVE-2022-22965 + CVE-2022-22970 + + + + + CVE-2022-22968 + CVE-2024-38820 + CVE-2025-22233 + + + + + CVE-2009-1190 + CVE-2011-2730 + CVE-2011-2894 + CVE-2014-3578 + CVE-2015-0201 + CVE-2015-5211 + CVE-2016-5007 + CVE-2018-11040 + CVE-2018-1199 + CVE-2018-1257 CVE-2018-1258 + CVE-2018-1271 + CVE-2018-1272 + CVE-2018-15756 + CVE-2021-22060 + CVE-2021-22096 + CVE-2024-22233 + CVE-2025-41249 + CVE-2026-41848 + + + + + CVE-2022-22950 + CVE-2023-20861 + CVE-2023-20863 + CVE-2024-38808 + CVE-2026-41849 + CVE-2026-41850 + CVE-2026-41851 + CVE-2026-41852 + + + + + CVE-2023-34034 + CVE-2023-34035 + CVE-2023-34042 + CVE-2026-22753 + CVE-2026-22754 + + + + + CVE-2010-3700 + CVE-2011-2731 + CVE-2011-2732 + CVE-2011-2894 + CVE-2012-5055 + CVE-2014-0097 + CVE-2014-3527 + CVE-2016-5007 + CVE-2016-9879 + CVE-2017-4995 + CVE-2018-1199 + CVE-2018-15801 + CVE-2019-11272 + CVE-2019-3795 + CVE-2020-5407 + CVE-2020-5408 + CVE-2021-22119 + CVE-2022-22976 + CVE-2022-22978 + CVE-2022-31692 + CVE-2023-20862 + CVE-2024-22234 + CVE-2024-22257 + CVE-2024-38810 + CVE-2024-38827 + CVE-2025-22223 + CVE-2025-22234 + CVE-2025-41232 + CVE-2025-41248 + CVE-2026-22746 + CVE-2026-22751 + + + + + CVE-2021-22112 + CVE-2022-22978 + CVE-2024-38821 + CVE-2026-22732 + CVE-2026-22747 + CVE-2026-41706 + CVE-2026-47838 + + + + + + + BIT-activemq-2020-26217 + BIT-activemq-2021-21341 + BIT-activemq-2021-21342 + BIT-activemq-2021-21343 + BIT-activemq-2021-21344 + BIT-activemq-2021-21345 + BIT-activemq-2021-21346 + BIT-activemq-2021-21347 + BIT-activemq-2021-21348 + BIT-activemq-2021-21349 + BIT-activemq-2021-21350 + BIT-activemq-2021-21351 + BIT-jenkins-2021-43859 + CVE-2013-7285 + CVE-2016-3674 + CVE-2017-7957 + CVE-2019-10173 + CVE-2020-26217 + CVE-2020-26258 + CVE-2020-26259 + CVE-2021-21341 + CVE-2021-21342 + CVE-2021-21343 + CVE-2021-21344 + CVE-2021-21345 + CVE-2021-21346 + CVE-2021-21347 + CVE-2021-21348 + CVE-2021-21349 + CVE-2021-21350 + CVE-2021-21351 + CVE-2021-29505 + CVE-2021-39139 + CVE-2021-39140 + CVE-2021-39141 + CVE-2021-39144 + CVE-2021-39145 + CVE-2021-39146 + CVE-2021-39147 + CVE-2021-39148 + CVE-2021-39149 + CVE-2021-39150 + CVE-2021-39151 + CVE-2021-39152 + CVE-2021-39153 + CVE-2021-39154 + CVE-2021-43859 + CVE-2022-40151 + CVE-2022-41966 + CVE-2024-47072 + + + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV commons-beanutils:commons-beanutils@1.11.0 (HIGH). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2014-0114 + CVE-2019-10086 + CVE-2025-48734 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV commons-collections:commons-collections@3.2.2 (CRITICAL, HIGH). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2015-6420 + CVE-2015-7501 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV org.apache.commons:commons-compress@1.28.0 (HIGH, MODERATE). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2012-2098 + CVE-2018-11771 + CVE-2018-1324 + CVE-2019-12402 + CVE-2021-35515 + CVE-2021-35516 + CVE-2021-35517 + CVE-2021-36090 + CVE-2023-42503 + CVE-2024-25710 + CVE-2024-26308 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV commons-configuration:commons-configuration@1.10 (LOW). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2025-46392 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV org.apache.commons:commons-email@1.6.0 (HIGH). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2017-9801 + CVE-2018-1294 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV commons-fileupload:commons-fileupload@1.6.0 (CRITICAL, HIGH, LOW). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2013-0248 + CVE-2013-2186 + CVE-2014-0050 + CVE-2016-1000031 + CVE-2016-3092 + CVE-2023-24998 + CVE-2025-48976 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV commons-httpclient:commons-httpclient@3.1 (MODERATE). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2012-5783 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV commons-io:commons-io@2.21.0 (HIGH, MODERATE). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2021-29425 + CVE-2024-47554 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV commons-lang:commons-lang@2.6 (MODERATE). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2025-48924 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV org.apache.commons:commons-collections4@4.5.0 (CRITICAL, HIGH). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2015-6420 + CVE-2015-7501 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV org.apache.commons:commons-lang3@3.20.0 (MODERATE). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2025-48924 + + + + commons-lang3 3.20.0 (PR #85, issue #84); commons-collections 3.2.2 -> commons-collections4 4.5.0 (PR #87, issue #86). commons-beanutils 1.11.0 class-injection guard (PR #110, issue #109). commons-text 1.15.0 + commons-io 2.21.0 + commons-email 1.6.0 + commons-httpclient 3.1 + commons-configuration 1.10 are addressed by caller-side validation; see SECURITY-MITIGATIONS.md. GAV org.apache.commons:commons-text@1.15.0 (CRITICAL). Tier 3 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.6 entry. + ]]> + CVE-2022-42889 + + + + + + + CVE-2007-5342 + + + + + CVE-2001-0590 + + + + + + 2.26.0 (PR #103, issue #102) closed all cataloged 13 CVEs at the version-bump level; 2.26.0 -> 2.26.1 follow-up in PR #105. The version line is the latest on Java 1.8 because Log4j 2.27+ requires Java 11+. GAV org.apache.logging.log4j:log4j-1.2-api@2.25.3 (MODERATE). Tier 2 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.8 entry. + ]]> + CVE-2026-34479 + + + + 2.26.0 (PR #103, issue #102) closed all cataloged 13 CVEs at the version-bump level; 2.26.0 -> 2.26.1 follow-up in PR #105. The version line is the latest on Java 1.8 because Log4j 2.27+ requires Java 11+. GAV org.apache.logging.log4j:log4j-api@2.25.3 (MODERATE). Tier 2 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.8 entry. + ]]> + CVE-2026-49844 + + + + 2.26.0 (PR #103, issue #102) closed all cataloged 13 CVEs at the version-bump level; 2.26.0 -> 2.26.1 follow-up in PR #105. The version line is the latest on Java 1.8 because Log4j 2.27+ requires Java 11+. GAV org.apache.logging.log4j:log4j-core@2.25.3 (CRITICAL, HIGH, LOW, MODERATE). Tier 2 CVEs have no Java 8 fix at a newer line; mitigation is documented in docs/SECURITY-MITIGATIONS.md T2.8 entry. + ]]> + CVE-2017-5645 + CVE-2020-9488 + CVE-2021-44228 + CVE-2021-44832 + CVE-2021-45046 + CVE-2021-45105 + CVE-2023-26464 + CVE-2025-68161 + CVE-2026-34477 + CVE-2026-34478 + CVE-2026-34480 + + + + + + + CVE-2016-2175 + CVE-2018-11797 + CVE-2018-8036 + CVE-2019-0228 + CVE-2021-27807 + CVE-2021-27906 + CVE-2021-31811 + CVE-2021-31812 + + + + + + + CVE-2012-0213 + CVE-2014-3529 + CVE-2014-3574 + CVE-2014-9527 + CVE-2017-12626 + CVE-2017-5644 + CVE-2019-12415 + + + + + CVE-2012-0213 + CVE-2022-26336 + + + + + + + CVE-2017-18640 + CVE-2022-1471 + CVE-2022-25857 + CVE-2022-38749 + CVE-2022-38750 + CVE-2022-38751 + CVE-2022-38752 + CVE-2022-41854 + + + + + + + CVE-2009-2625 + CVE-2012-0881 + CVE-2013-4002 + CVE-2020-14338 + CVE-2022-23437 + + + + + + + CVE-2026-8384 + + + + + BIT-jenkins-2021-28165 + BIT-kafka-2020-27218 + BIT-nifi-2020-27223 + BIT-solr-2020-27223 + BIT-spark-2020-27218 + BIT-spark-2020-27223 + CVE-2006-6969 + CVE-2011-4461 + CVE-2015-2080 + CVE-2016-4800 + CVE-2017-7656 + CVE-2017-7657 + CVE-2017-7658 + CVE-2017-9735 + CVE-2018-12536 + CVE-2018-12538 + CVE-2018-12545 + CVE-2019-10241 + CVE-2019-10246 + CVE-2019-10247 + CVE-2019-17632 + CVE-2019-17638 + CVE-2020-27218 + CVE-2020-27223 + CVE-2021-28165 + CVE-2021-34428 + CVE-2022-2191 + CVE-2023-26048 + CVE-2023-26049 + CVE-2024-13009 + CVE-2024-7708 + CVE-2024-8184 + CVE-2026-10051 + CVE-2026-1605 + CVE-2026-6790 + + + + + + + CVE-2019-14900 + CVE-2020-25638 + CVE-2026-0603 + + + + + CVE-2019-10219 + CVE-2020-10693 + CVE-2023-1932 + CVE-2025-35036 + + + + + + + CVE-2010-2057 + CVE-2011-4367 + + + + + + + CVE-2016-10006 + CVE-2017-14735 + CVE-2021-35043 + CVE-2022-28367 + CVE-2022-29577 + CVE-2023-43643 + CVE-2024-23635 + + + + + CVE-2010-3300 + CVE-2013-5679 + CVE-2013-5960 + CVE-2022-23457 + CVE-2022-24891 + + + + + + + CVE-2012-5784 + CVE-2014-3596 + CVE-2018-8032 + CVE-2019-0227 + CVE-2023-40743 + CVE-2023-51441 + + + + + CVE-2007-2353 + CVE-2012-5784 + CVE-2014-3596 + CVE-2018-8032 + CVE-2019-0227 + CVE-2023-40743 + CVE-2023-51441 + + + + + CVE-2014-9970 + + + + + CVE-2022-40149 + CVE-2022-40150 + CVE-2022-45685 + CVE-2022-45693 + CVE-2023-1436 + + + + + CVE-2024-47855 + + + + + CVE-2016-2510 + + + + + CVE-2025-66453 + + + + + CVE-2022-40705 + CVE-2022-45378 + + + + + CVE-2018-17201 + CVE-2018-17202 + + + + + + + CVE-2017-8028 + CVE-2024-38829 + CVE-2026-41720 + + + + + + + CVE-2026-3505 + + + + + CVE-2023-33202 + CVE-2025-8916 + CVE-2026-5588 + + + + + CVE-2023-33201 + CVE-2023-33202 + CVE-2024-29857 + CVE-2024-30171 + CVE-2024-30172 + CVE-2024-34447 + CVE-2025-14813 + CVE-2025-8885 + CVE-2026-0636 + CVE-2026-5598 + + + + + CVE-2025-58782 + + + + + CVE-2016-4437 + CVE-2019-12422 + CVE-2020-11989 + CVE-2020-13933 + CVE-2020-1957 + CVE-2021-41303 + CVE-2022-32532 + CVE-2022-40664 + CVE-2023-46749 + CVE-2026-23901 + CVE-2026-43827 + CVE-2026-49268 + + + + + CVE-2016-6802 + CVE-2020-17523 + CVE-2023-34478 + CVE-2023-46750 + CVE-2026-43828 + + + + + BIT-gradle-2020-11979 + CVE-2020-11979 + CVE-2020-1945 + CVE-2021-36373 + CVE-2021-36374 + GHSA-j45w-qrgf-25vm + + + + + CVE-2024-21742 + + + + + CVE-2022-31159 + + + + + CVE-2024-29857 + CVE-2024-30171 + CVE-2024-30172 + CVE-2025-8885 + + + + + CVE-2021-47621 + + + + + CVE-2021-37533 + + + + + CVE-2021-28490 + + + + + CVE-2016-15026 + + + + + CVE-2018-1000632 + CVE-2020-10683 + + + + + CVE-2017-5661 + + + + + CVE-2024-28168 + + + + + CVE-2020-7692 + CVE-2021-22573 + SNYK-JAVA-COMGOOGLEOAUTHCLIENT-575276 + + + + + CVE-2025-55163 + + + + + CVE-2023-1428 + CVE-2023-32731 + CVE-2023-32732 + PYSEC-2026-1425 + PYSEC-2026-1426 + PYSEC-2026-1427 + + + + + CVE-2022-25647 + SNYK-JAVA-COMGOOGLECODEGSON-1730327 + + + + + CVE-2018-10237 + CVE-2020-8908 + CVE-2023-2976 + SNYK-JAVA-COMGOOGLEGUAVA-1015415 + + + + + BIT-jenkins-2023-36478 + CVE-2023-36478 + + + + + CVE-2011-1498 + CVE-2012-6153 + CVE-2013-4366 + CVE-2014-3577 + CVE-2015-5262 + CVE-2020-13956 + + + + + CVE-2011-1498 + CVE-2012-6153 + CVE-2013-4366 + CVE-2014-3577 + CVE-2015-5262 + CVE-2020-13956 + + + + + CVE-2021-23792 + + + + + CVE-2020-28491 + + + + + CVE-2016-3720 + CVE-2016-7051 + + + + + CVE-2018-1000873 + + + + + CVE-2021-28170 + + + + + BIT-solr-2021-33813 + CVE-2021-33813 + + + + + CVE-2016-5725 + + + + + CVE-2022-45688 + CVE-2023-5072 + + + + + CVE-2015-6748 + CVE-2021-37714 + CVE-2022-36033 + CVE-2026-71497 + + + + + CVE-2020-15250 + + + + + CVE-2022-24613 + CVE-2022-24614 + + + + + CVE-2026-42577 + + + + + CVE-2020-11988 + + + + + CVE-2021-22569 + CVE-2022-3171 + CVE-2022-3509 + CVE-2022-3510 + CVE-2024-7254 + + + + + CVE-2019-13990 + + + + + CVE-2017-1000190 + + + + + BIT-solr-2020-13957 + BIT-solr-2023-50298 + CVE-2020-13957 + CVE-2023-50298 + + + + + CVE-2018-1270 + CVE-2018-1275 + CVE-2022-22971 + + + + + CVE-2013-4152 + CVE-2013-7315 + + + + + CVE-2018-25031 + CVE-2019-17495 + + + + + CVE-2022-40152 + + + + + CVE-2021-23926 + + + + + CVE-2016-4216 + + + + + CVE-2025-12383 + + + + + CVE-2021-28168 + + + + + CVE-2022-0839 + + + + + CVE-2025-59250 + + + + + CVE-2025-59250 + + + + + CVE-2023-22102 + + + + + CVE-2023-32697 + + + + + BIT-apisix-2023-44487 + BIT-aspnet-core-2023-44487 + BIT-contour-2023-44487 + BIT-dotnet-2023-44487 + BIT-dotnet-sdk-2023-44487 + BIT-envoy-2023-44487 + BIT-golang-2023-44487 + BIT-jenkins-2023-44487 + BIT-kong-2023-44487 + BIT-nginx-2023-44487 + BIT-nginx-gateway-2023-44487 + BIT-node-2023-44487 + BIT-node-min-2023-44487 + BIT-solr-2023-44487 + BIT-tomcat-2023-44487 + BIT-varnish-2023-44487 + CVE-2023-44487 + CVE-2024-22201 + CVE-2025-5115 + + + + + BIT-jenkins-2023-36478 + CVE-2023-36478 + + + + + BIT-apisix-2023-44487 + BIT-aspnet-core-2023-44487 + BIT-contour-2023-44487 + BIT-dotnet-2023-44487 + BIT-dotnet-sdk-2023-44487 + BIT-envoy-2023-44487 + BIT-golang-2023-44487 + BIT-jenkins-2022-2048 + BIT-jenkins-2023-44487 + BIT-kong-2023-44487 + BIT-nginx-2023-44487 + BIT-nginx-gateway-2023-44487 + BIT-node-2023-44487 + BIT-node-min-2023-44487 + BIT-solr-2023-44487 + BIT-tomcat-2023-44487 + BIT-varnish-2023-44487 + CVE-2022-2048 + CVE-2023-44487 + + + + + CVE-2015-0254 - --> + \ No newline at end of file diff --git a/projects/sitemanage/src/main/java/com/percussion/integrations/siteimprove/rest/PSSiteimprove.java b/projects/sitemanage/src/main/java/com/percussion/integrations/siteimprove/rest/PSSiteimprove.java index da01c5db83..7d6039755b 100644 --- a/projects/sitemanage/src/main/java/com/percussion/integrations/siteimprove/rest/PSSiteimprove.java +++ b/projects/sitemanage/src/main/java/com/percussion/integrations/siteimprove/rest/PSSiteimprove.java @@ -24,6 +24,7 @@ import com.percussion.metadata.data.PSMetadata; import com.percussion.metadata.data.PSMetadataList; import com.percussion.metadata.service.IPSMetadataService; +import com.percussion.role.service.impl.PSRoleService; import com.percussion.services.integrations.siteimprove.PSSiteImproveProviderService; import com.percussion.services.publisher.IPSEdition; import com.percussion.services.publisher.IPSEditionTaskDef; @@ -163,6 +164,16 @@ public Response storeSiteImproveToken(PSSiteImproveCredentials credentials) { Boolean validCredentials = providerService.validateCredentials(credentialsToValidate); if (validCredentials) { + // T2.14 hardening (epic #73, issue #223): CVE-2026-0603 second-order SQL injection. + // siteName becomes part of a String @Id primary key (PSMetadata.key) that Hibernate + // will later inline into UPDATE/DELETE predicates via InlineIdsOrClauseBuilder. A + // siteName with SQL metacharacters or control bytes turns the stored value into an + // injection lever. Reject before persistence. + if (PSRoleService.containsUnsafeIdentifierChar(credentials.getSiteName())) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("siteName contains characters that are unsafe as a metadata identifier") + .build(); + } ObjectNode jsonMap = MAPPER.createObjectNode(); credentialsToValidate.forEach(jsonMap::put); addSiteImproveTaskToPreExistingEditions(credentials.getSiteName()); @@ -206,6 +217,13 @@ public Response storeSiteImproveConfiguration(PSSiteImproveSiteConfigurations pu throw new Exception("Settings may not be null and a valid site name must be provided."); } + // T2.14 hardening (epic #73, issue #223): CVE-2026-0603 second-order SQL injection. + // Same protection as the credentials path: siteName flows into a String @Id key. + if (PSRoleService.containsUnsafeIdentifierChar(publishSettings.getSiteName())) { + throw new Exception( + "siteName contains characters that are unsafe as a metadata identifier"); + } + String siteConfigKey = SITEIMPROVE_CONFIGURATION_BASE_KEY + publishSettings.getSiteName(); ObjectNode publishSettingsJSON = MAPPER.createObjectNode(); publishSettingsJSON.put("doProduction", publishSettings.getDoProduction()); diff --git a/projects/sitemanage/src/main/java/com/percussion/role/service/impl/PSRoleService.java b/projects/sitemanage/src/main/java/com/percussion/role/service/impl/PSRoleService.java index f233ca04f9..674fca7aef 100644 --- a/projects/sitemanage/src/main/java/com/percussion/role/service/impl/PSRoleService.java +++ b/projects/sitemanage/src/main/java/com/percussion/role/service/impl/PSRoleService.java @@ -516,6 +516,15 @@ private void setHomepage(String roleName, String homepage) if (StringUtils.isBlank(roleName)) { throw new IllegalArgumentException("roleName must not be blank"); } + // T2.14 hardening (epic #73, issue #223): CVE-2026-0603 second-order SQL injection. + // PSMetadata.key is a String @Id primary key; Hibernate's InlineIdsOrClauseBuilder inlines + // that string into UPDATE/DELETE statements at a later time. If roleName carries a SQL + // metacharacter (quote, semicolon, comment, NUL) a later delete/update of the row could + // rewrite the predicate. Reject the input at the entry point instead. + if (containsUnsafeIdentifierChar(roleName)) { + throw new IllegalArgumentException( + "roleName contains characters that are unsafe as a metadata key identifier"); + } if (StringUtils.isBlank(homepage) || !(homepage.equals(HOMEPAGE_TYPE_DASHBOARD) || homepage.equals(HOMEPAGE_TYPE_EDITOR) @@ -696,4 +705,35 @@ public IPSRoleMgr getRoleMgr() { public void setRoleMgr(IPSRoleMgr roleMgr) { this.roleMgr = roleMgr; } + + /** + * Returns {@code true} if the supplied identifier string contains a character that is unsafe as a + * primary key value in a Hibernate-managed String @Id column. CVE-2026-0603 is a second-order SQL + * injection: a tainted identifier that is persisted today can be inlined into UPDATE/DELETE SQL + * at a later time by Hibernate's {@code InlineIdsOrClauseBuilder}. We reject the obvious SQL + * metacharacters and all C0/C1 control bytes up front so a future caller does not turn a stored + * identifier into an injection lever. + * + *

Public because {@code PSSiteimprove} lives in a different package and also composes + * user-controlled inputs into a String @Id column. The matching test {@code + * PSRoleServiceUnsafeIdTest} lives in the same package as this class. + */ + public static boolean containsUnsafeIdentifierChar(String value) { + if (value == null) { + return true; + } + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + // SQL metacharacters Hibernate will inline into an OR-clause identifier predicate. + if (c == '\'' || c == '"' || c == ';' || c == '\\' || c == '-' || c == '/' || c == '*' + || c == '(' || c == ')' || c == '\0' || c == '\n' || c == '\r' || c == '\t') { + return true; + } + // C0 (0x00-0x1F) and C1 (0x7F-0x9F) control characters. + if (c < 0x20 || (c >= 0x7F && c <= 0x9F)) { + return true; + } + } + return false; + } } diff --git a/projects/sitemanage/src/test/java/com/percussion/role/service/impl/PSRoleServiceUnsafeIdTest.java b/projects/sitemanage/src/test/java/com/percussion/role/service/impl/PSRoleServiceUnsafeIdTest.java new file mode 100644 index 0000000000..d42f1d34b0 --- /dev/null +++ b/projects/sitemanage/src/test/java/com/percussion/role/service/impl/PSRoleServiceUnsafeIdTest.java @@ -0,0 +1,100 @@ +/* + * Copyright 1999-2026 Percussion Software, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.percussion.role.service.impl; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit tests for the identifier safety helper added in T2.14 (epic #73, issue #223). The helper + * sits at the entry point of any user-controlled String value that flows into a Hibernate String + * {@code @Id} column, and is meant to block CVE-2026-0603 second-order SQL injection at the + * boundary before the tainted value is persisted. + * + *

JUnit 4 to match the rest of the role service test package. + */ +public class PSRoleServiceUnsafeIdTest { + + @Test + public void rejectsNull() { + assertTrue(PSRoleService.containsUnsafeIdentifierChar(null)); + } + + @Test + public void acceptsPlausibleRoleNames() { + assertFalse(PSRoleService.containsUnsafeIdentifierChar("Admin")); + assertFalse(PSRoleService.containsUnsafeIdentifierChar("Editor")); + assertFalse(PSRoleService.containsUnsafeIdentifierChar("Site_Author")); + assertFalse(PSRoleService.containsUnsafeIdentifierChar("Author.1")); + assertFalse(PSRoleService.containsUnsafeIdentifierChar("role with spaces")); + assertFalse(PSRoleService.containsUnsafeIdentifierChar("café")); + } + + @Test + public void rejectsSingleQuote() { + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin'")); + assertTrue(PSRoleService.containsUnsafeIdentifierChar("' OR 1=1")); + } + + @Test + public void rejectsDoubleQuote() { + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin\"")); + } + + @Test + public void rejectsSemicolon() { + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin;DROP TABLE users")); + } + + @Test + public void rejectsBackslash() { + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin\\")); + } + + @Test + public void rejectsDash() { + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin--comment")); + } + + @Test + public void rejectsSlashes() { + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin/x")); + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin/*x")); + } + + @Test + public void rejectsAsteriskAndParens() { + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin*")); + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin(1)")); + } + + @Test + public void rejectsNullAndControlCharacters() { + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin\u0000")); + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin\n")); + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin\r")); + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin\t")); + } + + @Test + public void rejectsC1ControlCharacters() { + // U+0085 (NEL) and U+009F (APC) are C1 controls and must be rejected. + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin\u0085")); + assertTrue(PSRoleService.containsUnsafeIdentifierChar("Admin\u009F")); + } +} diff --git a/system/ear/config/spring/beans.xml b/system/ear/config/spring/beans.xml index dd8bbddc5c..da7f3a488e 100644 --- a/system/ear/config/spring/beans.xml +++ b/system/ear/config/spring/beans.xml @@ -373,6 +373,15 @@ http://www.springframework.org/schema/context/spring-context.xsd"> true false create + + bind diff --git a/system/services/src/com/percussion/services/relationship/impl/PSRelationshipService.java b/system/services/src/com/percussion/services/relationship/impl/PSRelationshipService.java index a6b131866d..aee14ab1c4 100644 --- a/system/services/src/com/percussion/services/relationship/impl/PSRelationshipService.java +++ b/system/services/src/com/percussion/services/relationship/impl/PSRelationshipService.java @@ -615,8 +615,12 @@ public void reloadConfigs() throws PSException public List findByDependentId(int dependentId) { Session session = getSession(); + // T2.14 hardening (epic #73, issue #223): parameter binding instead of string concat. + // The call sites pass typed ints today, but the concat pattern is an unsafe precedent; + // a future caller that hands us a tainted string could otherwise build a SQLi surface. Query query = session - .createQuery("from PSRelationshipData " + " where dependent_id = " + dependentId); + .createQuery("from PSRelationshipData where dependent_id = :dependentId"); + query.setParameter("dependentId", dependentId); return query.list(); } @@ -927,8 +931,12 @@ public void updateRelationshipData( public List findByDependentIdConfigId(int dependentId, int configId) { Session session = getSession(); + // T2.14 hardening (epic #73, issue #223): parameter binding instead of string concat. Query query = session - .createQuery("from PSRelationshipData " + " where dependent_id = " + dependentId +" and config_id = " + configId); + .createQuery("from PSRelationshipData where dependent_id = :dependentId" + + " and config_id = :configId"); + query.setParameter("dependentId", dependentId); + query.setParameter("configId", configId); return query.list(); } diff --git a/system/src/main/resources/META-INF/validation.xml b/system/src/main/resources/META-INF/validation.xml new file mode 100644 index 0000000000..bac41686e3 --- /dev/null +++ b/system/src/main/resources/META-INF/validation.xml @@ -0,0 +1,28 @@ + + + + org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator + \ No newline at end of file