Installing self-created Nuget package forces use of latest version of a dependency, - nuget

I have created a nuget package for a library we use at my company. The library uses both Fluent NHibernate 1.3.0.717 and Structure Map 2.6.2.
Because some folks are using StructureMap 2.6.3, I created the dependencies of the package as:
<dependencies>
<dependency id="FluentNHibernate" version="[1.3,)" />
<dependency id="structuremap" version="[2.6.2,)" />
</dependencies>
And when the package shows up in NuGet it says that Structure Map >=2.6.2 is required. So far, so good.
Here's the issue:
When I go to add this library to my project, it always installs Structure Map 2.6.3. It even uninstalls 2.6.2 from my project in order to do so.
I don't see any sign that structure map 2.6.3 is a dependency of FluentNHibernate (or any of its dependencies) so I am absolutely baffled as to why it will not simply add my library with the FluentNHibernate dependencies and leave my StructureMap 2.6.2 alone.
I don't know if this would have anything to do with it, but we host the packages on a UNC share.

Read David Ebbo's blog series on NuGet Versioning and dependency resolution.
In short, we always pick the dependency with the lowest major and minor and highest build and revision number (based on the dependency's constraints). This is so that you automatically get bugs fixes (non breaking) when using a package as a dependency.

Related

NuGet does not download exact dependencies if other version is found in the cache

Problem:
NuGet refused to install a package into an empty folder after running nuget install "MyPackage" -Version "1.2.3.4" -OutputDirectory "foo". It complained that the version of a dependency was not the expected one.
It was true that MyPackage required a dependency with an exact version, of which only a slightly lower version was in my local cache. Problem is that the dependency was existing on the server and NuGet could see it. I would expect that NuGet just downloads the correct version from the server, but it didn't.
I could workaround this by adding the -NoCache option to the command, but this disables the cache completely, so that much more is downloaded than actually needed. Is there a better way to solve this?
Additional Details:
The dependency of MyPackage was defined like this:
<dependencies>
<dependency id="MyDependency" version="[5.0.2.1]" />
</dependencies>
The version of MyDependency in my local cache was 5.0.1.2. As said, NuGet complained that this is not exactly the required version ans cancelled the installation, even though 5.0.2.1 was on the server. After adding -NoCache to the command, NuGet downloaded the correct version. After that, -NoCache was not needed anymore to install MyPackage. Version 5.0.2.1 of MyDependendy was then taken from the cache as expected.
My NuGet version is: 6.2.1.2
Side note: using the exact version is important, i.e., a less strict rule for the dependency is no option.

How does .NET resolve different versions of the same package?

This question pertains to .NET 5+, not .NET Framework.
Consider the following dependency tree:
MyWebsite has package references to RandomWebLibrary 1.0.0 and RandomJsonLibrary 2.0.0.
The NuGet package RandomWebLibrary 1.0.0 has a package reference to RandomJsonLibrary 1.0.0.
The NuGet package RandomJsonLibrary has no dependencies.
My questions:
What version(s) of RandomJsonLibrary will be loaded at runtime?
What happens if RandomJsonLibrary 2.0.0 has a completely different API than RandomJsonLibrary 1.0.0?
Can the author of MyWebsite do anything to fix problems that arise from having multiple versions of RandomJsonLibrary in the dependency tree? Is there an equivalent of .NET Framework's binding redirects in .NET 5+?
I'm asking out of curiosity, not because I am encountering a problem. For reference, here is the documentation on Understanding AssemblyLoadContext which seems relevant but did not answer my question.
These questions are answered by the documentation page How NuGet resolves package dependencies. The "Dependency resolution with PackageReference" section is what's relevant to this question since we are talking .NET 5+.
When the package graph for an application contains different versions of the same package, NuGet chooses the package that's closest to the application in the graph and ignores all others. This behavior allows an application to override any particular package version in the dependency graph.
In the example below, the application depends directly on Package B with a version constraint of >=2.0. The application also depends on Package A which in turn also depends on Package B, but with a >=1.0 constraint. Because the dependency on Package B 2.0 is nearer to the application in the graph, that version is used:
To answer the original questions:
RandomJsonLibrary 2.0.0 will be loaded at runtime.
I believe RandomWebLibrary will throw exceptions at runtime if RandomJsonLibrary 1.0.0 and 2.0.0 have incompatible APIs.
The author of MyWebsite can choose the exact version of any dependent package by installing that package directly into MyWebsite. In the case of RandomJsonLibrary, the author of MyWebsite should probably downgrade to RandomJsonLibrary 1.0.0 to prevent RandomWebLibrary from breaking. AFAIK there are no binding redirects in .NET 5+.

XRay fails to detect vulnerability in NuGet package dependency

I created a test NuGet package which specifies a dependency on jQuery 1.4.2. XRay correctly detects the security issues on jQuery when uploaded to my Artifactory NuGet server. However, when I upload my test NuGet package which lists jQuery 1.4.2 as a dependency, XRay does not flag my package as a vulnerable.
1) Tested that jQuery 1.4.2 Nuget package in my Artifactory server is correctly detected as vulnerable.
2) Added a dependency to my test package that list jQuery 1.4.2. (I suspected a case-sensitivity issue so I also tried a lowercase dependency as "jquery").
3) Tried other known vulnerable packages besides jQuery
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>RogerCruz.VulnerabilitiesGalore</id>
<title>VulnerabilitiesGalore</title>
<version>1.0.4.0</version>
<owners>Roger Cruz</owners>
<authors>Roger Cruz</authors>
<releaseNotes>A package that depends on known vulnerable packages. Use this to test vulnerability scanners.</releaseNotes>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Test package with known vulnerabilities</description>
<copyright>Copyright Roger Cruz</copyright>
<dependencies>
<dependency id="jQuery" version="[1.4.2]"/>
</dependencies>
</metadata>
<files>
</files>
</package>
These are the commands I am using to create my test NuGet package and to push them to the Artifactory+XRay cloud trial instances.
nuget.exe pack VulnerabilitiesGalore.nuspec
nuget push .\RogerCruz.VulnerabilitiesGalore.1.0.4.nupkg -Source Trial
Artifactory reports my test package to have one dependency. You can see the following property when browsing the package.
nuget.dependency jQuery:[1.4.2]:
In all of my test tries, XRay is not detecting my test package (RogerCruz.VulnerabilitiesGalore) as vulnerable despite having a specified dependency on jQuery 1.4.2 which is vulnerable.
My expectation is that it should have detected it because of this statement:
"Deep Recursive Scan Through All Layers of a NuGet package
Xray recursively peels away the different layers of your NuGet packages and their dependencies ensuring that every software artifact that is included in your software has been scanned for issues and vulnerabilities. "
Src: https://jfrog.com/integration/nuget-xray/
The package RogerCruz.VulnerabilitiesGalore doesn't include jQuery:1.4.2 in it. It`s related to it as a direct runtime dependency as shown in the .nuspec descriptor file.
Deep Recursive Scan means the relation of the package physically inside another package.
for example: if the RogerCruz.VulnerabilitiesGalore package would include jQuery:1.4.2 in it, then JFrog Xray would detect it as vulnerable and recursively scan it by opening package by package like peeling an onion.
A proper use case in the scenario above is building the RogerCruz.VulnerabilitiesGalore by itself or use it as a dependency of another project. At build time the direct dependency jQuery:1.4.2 will be resolved from the remote repository and JFrog Xray will be able to scan it.
In order to achieve full scanning of NuGet projects and it`s transitive dependencies, I would recommend building your project with JFrog CLI
JFrog Xray will know how to analyze the build-info produced by it, scan the project and its dependencies (include transitive)

How to create a package that is most likely not to cause versioning problems?

I created a NuGet package with an empty logger and my package depends on Microsoft.Extensions.Logging.Abstractions.
My PackageReference line and my dependency in the .nuspec file are set to 1.0.0 with no special syntax which I understand means >=.
My empty logger works just fine with this version and I thought using the lowest working version of the abstractions lib would make my package easier to consume by applications which are likely to have greater versions.
However, when I've referenced my package from an xUnit test project I have a red compiler error CS1705.
My test project references two packages:
The project its testing, which is an ASP.NET Core Razor Pages site that in turn references the same logging abstractions package which is included in Microsoft.AspNetCore.App 2.2.0 metapackage.
My empty logger package, which, in turn references the logging abstractions 1.0.0.0 as I have described.
Compiler error from the test proj says:
Assembly (Razor Pages proj) uses (Abstractions 2.2.0.0) which has a higher version than referenced assembly (Abstractions) with identity (Abstractions 1.0.0.0).
My package can use the higher version so what am I missing?
Edit
Here's a high fidelity diagram ;)
T is "xUnit Proj".
W is the "Website Proj" under test.
E is the empty logger package (Evoq.Instrumentation on nuget.org)
A is metapackage Microsoft.AspNetCore.App 2.2.0
L is Microsoft.Extensions.Logging.Abstractions
There's the nearest wins rule, which I think means that the dependency from T to L via E would win and version 2.0.0 would be used but I'd expect a package downgrade warning not a hard compiler error.
Nearest wins: https://learn.microsoft.com/en-us/nuget/consume-packages/dependency-resolution#nearest-wins
Edit 2
It just occured to me that T > W is a project reference. So maybe that's short-circuiting the NuGet resolution. I'll add a ref from T to A directly and see if that solves it.
I forgot T > W is a project reference. So I think that was short-circuiting the NuGet resolution I was expecting to take place.
I added a ref from T to A directly and that solved it.

Understanding eclipse maven dependency hierarchy

I want to understand the dependencies for a multi-module maven project and for that referred to eclipse dependency hierarchy.
I did understand fairly, however some of the things I am not able to understand at all.
Below is the screen shot.
The things which I didn't understand are:
--> managed from 1.0.2 [Compile}
--> managed from 1.0.2 (omitted for conflict with 1.0.0) [Compile]
I did search online but I got information in traces. Can anyone help me understand what they mean in easy to understand?
Thanks.
Maven builds a flat classpath from the dependency tree each for compiling ([compile]), for testing, and for running.
In a flat classpath, unlike OSGi, a dependency can only exist in one version. In your cropped screenshot, there is on the second level among other things:
kafka-streams 1.0.2 and
kafka-clients 1.0.0.
kafka-streams 1.0.2 requires kafka-clients 1.0.2 which conflicts to kafka-clients 1.0.0. Therefore kafka-streams 1.0.2 is omitted for conflicts with 1.0.0 even if the version 1.0.2 is required here ("managed from 1.0.2").
More detailed:The classpath which is used to compile or run a plain Java application is flat: all required libraries are globally specified as an ordered list. It is not possible to use a library of a specific version for one package and for another package the same library in a different version.In Maven dependencies builds a tree: each dependency might have its own dependencies. Maven maps the tree of dependencies to the classpath, an ordered list of libraries. If in the Maven dependencies tree the same library exists in different versions, it is not possible to create a flat classpath. This is a conflict.This conflict is resolved by picking one version and omitting all other versions. At the place where the picked version is used instead of the required version, (managed from <required but not picked version>) and (omitted for conflict with <picked version to use instead>) is displayed.In addition, Maven can create different classpaths to compile, to test or to run a Java application via so-called scopes. The [compile] scope is the default scope for using a library in all tasks: compiling, testing and running.
Make sure that the versions specified in the pom.xml file are compatible with each other (which is not yet the case in your screenshot): you have to upgrade kafka-clients from 1.0.0 to 1.0.2 (or downgrade the other libraries).