You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by "lhotari (via GitHub)" <gi...@apache.org> on 2026/08/04 07:49:47 UTC

[PR] [improve][io] Replace Spring Framework with cron-utils in CronTriggerer [pulsar]

lhotari opened a new pull request, #26269:
URL: https://github.com/apache/pulsar/pull/26269

   ### Motivation
   
   `CronTriggerer` was the only production use of the Spring Framework in the Pulsar code base. It pulled `spring-context` and `spring-core` (3.3 MB) into the batch-source connector NARs just to parse a cron expression and run a timer.
   
   Removing the dependency also removes Pulsar's exposure to Spring Framework CVEs. The pinned version, 6.2.12, falls within the affected range (`6.2.0` -> `6.2.18.1`) of four CVEs published on 2026-06-09:
   
   | CVE | Issue |
   |---|---|
   | [CVE-2026-41848](https://www.cve.org/CVERecord?id=CVE-2026-41848) | Denial of service via ReDoS in `AntPathMatcher` (CWE-1333) |
   | [CVE-2026-41850](https://www.cve.org/CVERecord?id=CVE-2026-41850) | Algorithmic denial of service via SpEL expressions (CWE-407) |
   | [CVE-2026-41851](https://www.cve.org/CVERecord?id=CVE-2026-41851) | Denial of service via an unbounded SpEL expression cache (CWE-770) |
   | [CVE-2026-41852](https://www.cve.org/CVERecord?id=CVE-2026-41852) | Arbitrary zero-argument method invocation in SpEL (CWE-863) |
   
   Pulsar only used Spring's cron scheduling, so it neither evaluated SpEL nor used `AntPathMatcher`, and was unlikely to be exploitable through those paths. Dropping the dependency nevertheless removes the flagged artifacts from the connector NARs and ends the need to track Spring CVEs at all.
   
   ### Modifications
   
   - Replace `ThreadPoolTaskScheduler` + `CronTrigger` with [cron-utils](https://github.com/jmrozanec/cron-utils) (`CronType.SPRING53`; 175 kB, Apache-2.0, `slf4j-api` its only dependency) and a self-rescheduling single-threaded `ScheduledExecutorService`. The next firing is derived from the completion time of the previous one, so firings never overlap — matching how Spring's `CronTrigger` behaved.
   - Lower-case leading-`@` expressions before parsing: Spring matched the `@daily` style macros case-insensitively, cron-utils only accepts lower case.
   - Parse the expression in `init()`, so a malformed expression fails there rather than at the first scheduling attempt.
   - Drop the now unused `spring-context` from `batch-data-generator` (cron-utils is bundled into the NAR transitively) and `spring-core` from the broker test dependencies, replacing the single `CollectionUtils.isEmpty()` use in `AdminApiHealthCheckTest` with `List.isEmpty()`.
   - Remove the `spring` version and both library aliases from the version catalog, and wire up the previously orphaned `cron-utils` version, bumped `9.1.6` -> `9.2.1` because `CronType.SPRING53` requires 9.2.0+.
   
   #### Backward compatibility of the cron dialect
   
   Existing `__CRON__` configurations must keep working, so the replacement was validated against Spring rather than assumed. A differential harness compared `CronExpression` (Spring 6.2.12) with cron-utils `SPRING53` over **4,589,882** next-fire comparisons — 528 expressions x 8 time zones x 37 start instants x 6 chained steps:
   
   - **No parsing differences.** Six-field syntax, `L` / `W` / `LW` / `#` / `?`, named and numeric day-of-week, all seven macros, whitespace and case all agree, and both reject the same malformed input with `IllegalArgumentException`.
   - **99.9944% identical firing times.** All 255 differing results are in DST-observing zones, where an expression falling in a shifted or repeated hour can lose one firing per year. There were **no** differences in fixed-offset zones (UTC, `Asia/Kolkata`, `America/Sao_Paulo`).
   
   Quartz was also evaluated and rejected: it cannot parse 15 of 17 of the expressions used here — including `* * * * * *` from `BatchSourceTest` — because it forbids specifying both day-of-month and day-of-week, and it numbers day-of-week `1=SUN` against Spring's `1=MON`, which would silently shift every numeric schedule by a day.
   
   ### Verifying this change
   
   - [x] Make sure that the change passes the CI checks.
   
   This change added tests and can be verified as follows:
   
   - Adds `CronTriggererTest` (33 cases), covering the cron dialect, repeated scheduling, `stop()` behaviour, thread naming, non-overlapping firings and trigger-failure handling. The expected firing times were generated from Spring itself, so they pin down the previous behaviour.
   - Verified locally: `CronTriggererTest` green over 6 consecutive runs with retries disabled; `quickCheck`, `sanityCheck`, `spotlessCheck`, `checkstyleMain`, `checkstyleTest` all pass; `BatchSourceExecutorTest`, `BatchSourceConfigParseTest`, `SourceConfigUtilsTest`, `TestCmdSources` and `AdminApiHealthCheckTest` pass.
   - Confirmed the built `pulsar-io-batch-data-generator` NAR now bundles `cron-utils-9.2.1.jar` and no Spring jars.
   
   ### Does this pull request potentially affect one of the following parts:
   
   *If the box was checked, please highlight the changes*
   
   - [x] Dependencies (add or upgrade a dependency)
   - [ ] The public API
   - [ ] The schema
   - [ ] The default values of configurations
   - [ ] The threading model
   - [ ] The binary protocol
   - [ ] The REST endpoints
   - [ ] The admin CLI options
   - [ ] The metrics
   - [ ] Anything that affects deployment
   
   Dependency changes: removes `org.springframework:spring-context` and `org.springframework:spring-core` (6.2.12) from the build entirely; adds `com.cronutils:cron-utils` 9.2.1 (Apache-2.0) to `pulsar-io-batch-discovery-triggerers`. No LICENSE/NOTICE updates are needed — the server and shell distributions exclude `.nar` files, so the Spring jars were never listed there.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [improve][io] Replace Spring Framework with cron-utils in CronTriggerer [pulsar]

Posted by "merlimat (via GitHub)" <gi...@apache.org>.
merlimat merged PR #26269:
URL: https://github.com/apache/pulsar/pull/26269


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@pulsar.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org