Skip to content

Conversation

bestbeforetoday
Copy link
Contributor

@bestbeforetoday bestbeforetoday commented Jun 3, 2023

Closes #10247

@bestbeforetoday
Copy link
Contributor Author

I am not sure what the correct course of action is here. The version of com.google.j2objc:j2objc-annotations specified by com.google.guava:guava:32.0.0-android (2.8) does not match the one specified by com.google.protobuf:protobuf-java-util:3.22.3 (1.3). Does protobuf-java-util need to be updated first or is there alternative resolution?

@sanjaypujare
Copy link
Contributor

Does protobuf-java-util need to be updated first or is there alternative resolution?

I checked and the latest non-RC version 3.23.2 also uses 1.3 so not sure which version you can update to. If everything works out without upgrading protobuf-java-util may be it's okay?

@bestbeforetoday bestbeforetoday force-pushed the guava branch 2 times, most recently from 8baf8b4 to 54c8c47 Compare June 7, 2023 08:36
@bestbeforetoday
Copy link
Contributor Author

Thank you for the input. I noticed there was no release version of protobuf-java-util with a more recent dependency and wondered if it was necessary to update protobuf-java-util first.

I have changed the transitive dependency version checking logic slightly, which makes it more similar to Maven's and avoids the build failure. Also specified an explicit dependency in the Maven example project to ensure correct transitive dependency version selection. I am not sure if these changes are really satisfactory. Particularly the Gradle version check is using a deprecated Gradle class to parse package versions. I guess the alternative is to use a different version parser, or to implement some version comparison logic in this project.

Any guidance or help would be appreciated.

@bestbeforetoday bestbeforetoday marked this pull request as ready for review June 7, 2023 12:03
@sanjaypujare sanjaypujare added the kokoro:run Add this label to a PR to tell Kokoro the code is safe and tests can be run label Jun 9, 2023
@grpc-kokoro grpc-kokoro removed the kokoro:run Add this label to a PR to tell Kokoro the code is safe and tests can be run label Jun 9, 2023
@ejona86
Copy link
Member

ejona86 commented Jun 9, 2023

I have changed the transitive dependency version checking logic slightly, which makes it more similar to Maven's and avoids the build failure

Hehe. You are giving Maven too much credit. It doesn't compare versions and choose the latest. Maven does a breadth-first scan of the dependency tree and always chooses the first version is finds ("nearest definition"). So it trivially makes bad decisions. The check is "would Maven downgrade dependencies," mirroring Maven Enforcer's requireUpperBoundDeps which detects the same. The check assumes Gradle made a good version decision, and just checks that Maven would have made the same decision. You could use a comparison (but not with VersionNumber because it is being removed), but you'd need to reverse the comparison: version < goldenVersion.

The proper solution is to add an explicit dependency (like you did for the example) or to reorder the dependency list. Explicit dependencies always work, but reordering the dependency list can significantly reduce the burden at times.

@bestbeforetoday
Copy link
Contributor Author

Thanks for the response. I was referring to Maven's requireUpperBoundDeps, not to Maven's version resolution in general, since the function I changed is supposed to implement similar checks to Maven's requireUpperBoundDeps.

Are you sure that it is an error for a transitive dependency to want an older version than the one resolved by Gradle? I thought it was supposed to be the other way, where it is an error for the resolved version to be older than one required by a transitive dependency since it might be relying on functionality not available in the resolved version. In which case the check should be version > goldenVersion, as I have implemented.

Adding an explicit dependency sounds reasonable. However, will that still cause the existing check to fail since the resolved version does not match exactly the one requested by all transitive dependencies?

If using VersionNumber is not an acceptable implementation approach, please could you advise on what should be used?

@ejona86
Copy link
Member

ejona86 commented Jun 12, 2023

If using VersionNumber is not an acceptable implementation approach, please could you advise on what should be used?

Don't touch the checker. It is doing exactly what it's supposed to be doing.

In which case the check should be version > goldenVersion, as I have implemented.

That means it is checking for cases that Maven would use a newer version than Gradle. Upgrading is okay, so this would only fail in cases we don't care about. But also, Gradle is already choosing the highest transitive dependency.

Since Gradle is already choosing reasonable versions, simply checking that Maven would choose something else is simple and useful.

However, will that still cause the existing check to fail since the resolved version does not match exactly the one requested by all transitive dependencies?

No, the check just verifies the version of the first transitive dependency it encounters of each artifact. So it only checks the version that Maven would have used.

        if (found.contains(artifact))
            continue

You resolve this failure exactly like you would in Maven, and then the check starts passing as it would in Maven. It is dissimilar from dependencyConvergence, which requires a lot of work for a very brittle system (each dependency excluded is just a future bug).

@bestbeforetoday
Copy link
Contributor Author

Thank you for the clear explanation. As soon as I get a chance I'll push an update with an explicit dependency and the change to the checking code reverted.

Maven requireUpperBoundDeps checks that the version for each dependency resolved during a build, is equal to or higher than all transitive dependency declarations. It is not required for a resolved dependency to exactly match all transitive dependency declarations.

As a proof-of-concept, this implementation uses Gradle's VersionNumber utility, which is deprecated and scheduled to be removed in Gradle 9. An alternative (or custom) version comparison utility should be used.
Revert change to requireUpperBoundDepsMatch since explicit dependencies
are the correct way to resolve the version inconsistency in transitive
dependencies.
@sanjaypujare sanjaypujare added the kokoro:run Add this label to a PR to tell Kokoro the code is safe and tests can be run label Jun 12, 2023
@grpc-kokoro grpc-kokoro removed the kokoro:run Add this label to a PR to tell Kokoro the code is safe and tests can be run label Jun 12, 2023
@sanjaypujare
Copy link
Contributor

CC @sergiitk

Copy link
Contributor

@sanjaypujare sanjaypujare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@sanjaypujare sanjaypujare requested a review from ejona86 June 12, 2023 19:39
Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@ejona86 ejona86 merged commit ae59afb into grpc:master Jun 12, 2023
@bestbeforetoday bestbeforetoday deleted the guava branch June 13, 2023 14:29
@bestbeforetoday
Copy link
Contributor Author

Will you backport this change to whichever branch will produce the next published release, or should I raise a PR with that backport? If it helps for me to raise a PR with a cherry-pick of this commit, please just let me know which branch(es) I should raise against.

@ejona86
Copy link
Member

ejona86 commented Jun 13, 2023

The release is going out today-ish. Last week I considered whether we'd want to backport this (before it was merged), but the Guava update is so big it scared me too much. 32.0.x is a bit too big to rush it out. And the fix in 32.0.1 was exactly because of the code change to fix the CVE. If the grpc release was in two or three more weeks, I'd be more comfortable with this. I just see too many potential issues that could prevent people from upgrading quickly. Also, users can upgrade Guava themselves, whereas with #10260 they can't.

We lived with the CVE for a while as "it didn't actually matter" because the code wasn't used and most deployments wouldn't be vulnerable if it were. FileBackedOutputStream doesn't really change that. Downstream can upgrade Guava themselves, now, which is a better place to be.

For the same reasoning, I don't think we'll want a patch release for this. That does make me uncomfortable, because we take vulnerabilities seriously and we want to help make the ecosystem healthy, but the practical side of me is even more uncomfortable because it seems too much risk for limited gain.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update guava dependency to address CVE-2023-2976
4 participants