okta/okta-spring-boot

Override of Jackson version is ignored in user's applications

snicoll opened this issue · 7 comments

I'm submitting a

  • bug report

Background info

This project overrides the jackson version that it uses to compile and test the starter:

<version>2.12.3</version>

This is problematic as this override is ignored in user's application so the tests aren't arguably testing with the same environment.

Expected behavior

Starter uses dependency management from Spring Boot, adding versions for the specific artifacts that the starter integrates with (Okta).

What went wrong?

Nothing yet but that looks a technical debt to me that can lead to issues post release.

Steps to reproduce

n/a

SDK Version

n/a

Hi @snicoll,

Thanks for reporting this.

I'll submit an internal ticket for the team to review.

Internal Ref: OKTA-405605

Hey @snicoll!

Is there any linting or other tooling we can check for issues like this?

Jackson version is a particularly interesting one though, given the series of vulns reported against 2.10 (IIRC), we tried to stay on the latest patch release, to avoid transitively bringing any sec issues.

Given that start.spring.io uses a version range compatibility there is likely to be minor dep version differences between any libraries.
That said, I realize that us including the jackson-bom doesn't help the situation.

Any thoughts on the best path forward?

Is there any linting or other tooling we can check for issues like this?

I am not sure what you mean by that. If you put spring-boot-dependencies as the first bom you import and you don't specify versions in your build you should be fine.

we tried to stay on the latest patch release, to avoid transitively bringing any sec issues.

What I am trying to say is that it doesn't matter what version you specify. In a standard Spring Boot application, Spring Boot's dependency management is going to select the jackson version to use and your override won't be taken into account. That's the root of the problem as the project may be built with a different environment.

Given that start.spring.io uses a version range compatibility there is likely to be minor dep version differences between any libraries.

I don't understand how start.spring.io is involved here.

Any thoughts on the best path forward?

I would advise to make sure to build against the latest of the Spring Boot generation(s) that you support, potentially tracking earlier milestone if you can. I would also advise to not try to support too many Spring Boot versions for the same starter generation. I hope that helps.

Thanks for reporting this @snicoll! We'll address this.

Sorry @snicoll, I think there is a little confusion here, hopefully, I can try to clear this up

I don't understand how start.spring.io is involved here.

Start.spring.io, introduces a dependency version range, e.g. this project's current version is compatible with Spring Boot 2.5.*
(This problem isn't specific to start.spring.io, but for the sake of keeping the conversation focused, that's where the compatibility range is defined. It's also defined in our README, for folks not using start.spring.io).

This means that any Spring Boot 2.5.x version could have a different version of Jackson (or any other lib we are testing against). For example, if Spring Boot 2.5.2 was released tomorrow with a dep on jackson-bom v2.11.5, and the current version of the Okta Spring Boot Starter would have been tested against 2.11.3. So there is always a small risk of version drift.

Here is where it gets tricky. We also want to make sure we are scanning the project for vulnerabilities, so we don't transitively introduce them to downstream projects. It's a PITA to separate out dependencies managed by the Spring BOM, and other dependencies.

This is why I was asking about tooling/linting because it's not easy to do this with existing tools, OWASP dep check, Synk, etc.

From a purely Maven point of view, there is also no guarantee that a user is using the spring-boot-dependencies bom, in which case Maven should resolve the version from the shortest branch. But, I'll admit I might be overthinking this one.

Anyway, maybe for this project, it's best/easier to just be in lockstep with the deps from spring-boot-dependencies, given that many of the runtime dependencies overlap, couple that with the fact that Spring Boot puts out a release every ~3-4 weeks and that's a decent level of assurance. It's not a perfect solution, but we are open to other thoughts/suggestions!

Thanks for bringing this up and sorry for the long-winded response!!

For example, if Spring Boot 2.5.2 was released tomorrow with a dep on jackson-bom v2.11.5, and the current version of the Okta Spring Boot Starter would have been tested against 2.11.3. So there is always a small risk of version drift.

Yes, I am aware of that but fixing the version yourself means that you need to make sure it stays current and you're not drifting the version in your build. Spring Boot has a very conservative policy with regards to third party dependency upgrades in maintenance release. In a maintenance release of Spring Boot, we will only upgrade to a maintenance release of Jackson (i.e. 2.11.x).

Here is where it gets tricky. We also want to make sure we are scanning the project for vulnerabilities, so we don't transitively introduce them to downstream projects.

In an ideal world, the dependency has released a bugfix version and a version of Spring Boot is available that uses that version. Of course, that's just the ideal situation. I am not aware of a tool that would help you with that.

From a purely Maven point of view, there is also no guarantee that a user is using the spring-boot-dependencies bom, in which case Maven should resolve the version from the shortest branch.

Absolutely but the chances that your users are using it is far more likely than them not using it. For that reason, using the version provided by Spring Boot's dependency management is quite important, especially when the starter is hosted on start.spring.io as that is actually a given.

Anyway, maybe for this project, it's best/easier to just be in lockstep with the deps from spring-boot-dependencies, given that many of the runtime dependencies overlap, couple that with the fact that Spring Boot puts out a release every ~3-4 weeks and that's a decent level of assurance. It's not a perfect solution, but we are open to other thoughts/suggestions!

Given the release cadence of this starter, I would said so as well. What you've raised is interesting, I wonder if @wilkinsona has additional thoughts on that.

We have to assume a certain amount of backwards compatibility across maintenance releases. Using Jackson as an example again, Spring Boot 2.5.x uses Jackson 2.12.x. Given that the Jackson 2.12.x version will vary across Spring Boot 2.5.x versions, I think it's sufficient for you to test against any Jackson 2.12.x version. If it were me, I'd probably test against the latest version as, in an ideal world, that's what your users will be using. Aligning with the dependency management in spring-boot-dependencies is a pretty good way to achieve that as we update its dependency management prior to each Spring Boot maintenance release.