NET6 CVE-2019-0980 CVE-2019-0981 - possible bug in .deps.json trans deps resolution
Hi,
we are running NET6 images , but we get this 2019 vulnerability reported when running our trivy scans.
is this actually expected or could it be a false positive?
atm we added
CVE-2019-0980 CVE-2019-0981
but we cannot detect the source of the vulnerability after we updated all our packages
System.Private.Uri │ CVE-2019-0980 │ HIGH │ 4.3.0 │ 4.3.2
i am not sure we actually use this package, i see it not appearing at all after running
dotnet build
and then
dotnet publish
and checking the .deps.json file
i think the recently introduced support for .deps.json might be buggy?
dotnet list package --include-transitive
> System.Numerics.Vectors 4.5.0
> System.ObjectModel 4.3.0
> System.Private.DataContractSerialization 4.3.0
> System.Private.Uri 4.3.2
> System.Reflection 4.3.0
> System.Reflection.Emit 4.3.0
> System.Reflection.Emit.ILGeneration 4.3.0
so seems we already run the latest System.Private.Uri: 4.3.2, so it's kind of weird.
coudl you provide a trivy switch by selecting e.g. only NET6 ? maybe some scans are running for other deployments target that we dont run in production?
We have the same issue. Is there a way to exclude all packages that use the installed runtime (and thus are not really packages)?
pls if you also experience a similar issue add a 👍 on top!
I agree, the method of scanning deps.json for vulnerabilities is not valid, or at least needs some tweaking. We're using the latest versions of System.Private.Uri included with .net 6 but aqua is flagging these containers as vulnerable:
/app $ cat <redacted>.deps.json | grep Uri
"System.Private.Uri": "4.3.0"
"runtime.unix.System.Private.Uri/4.3.0": {
"System.Private.Uri": "4.3.0",
"System.Private.Uri/4.3.0": {
"runtime.unix.System.Private.Uri": "4.3.0"
"runtime.unix.System.Private.Uri/4.3.0": {
"System.Private.Uri/4.3.0": {
/app $ find / -name "*Uri*"
/usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.9/System.Private.Uri.dll
/app $ exiftool /usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.9/System.Private.Uri.dll | grep -w Version
ExifTool Version Number : 12.40
Linker Version : 11.0
OS Version : 4.0
Image Version : 0.0
Subsystem Version : 4.0
File Version Number : 6.0.922.41905
Product Version Number : 0.0.0.0
File Version : 6.0.922.41905
Product Version : 6.0.9-servicing.22419.5+163a63591cf9e9b682063cf3995948c2b885a042
Assembly Version : 6.0.0.0
Hello @jkone27 , @JoostvdB94 Thanks for your reports!
@jkone27 i looked your screen shoot - if i understand correctly - this *.deps.json file doesn't contain System.Private.Uri, right?
This is very strange... Can you use --format json --list-all-pkgs flags and scan again?
You can see filepath in Target field. e.g.:
trivy -d image -f json --list-all-pkgs -o result.json mcr.microsoft.com/dotnet/sdk
...
{
"Target": "usr/share/dotnet/sdk/6.0.402/Microsoft.TestPlatform.PlatformAbstractions.deps.json",
"Class": "lang-pkgs",
"Type": "dotnet-core",
"Packages": [
{
"Name": "Microsoft.CodeAnalysis.PublicApiAnalyzers",
"Version": "3.3.4-beta1.21554.2",
"Layer": {
"DiffID": "sha256:299937ab7d353b110721d6c2a7a0ea9943290e18a6899aaf43f197458e1785f9"
}
},
...
Perhaps another *deps.json file contains System.Private.Uri.
@plaisted your <redacted>.deps.json contains "System.Private.Uri": "4.3.0". if i understand correctly - it is not lastest version(https://www.nuget.org/packages/System.Private.Uri).
CVE-2019-0980 and CVE-2019-0981have fixed version == "4.3.2".
It looks like Trivy works correctly.
Tell me if i am wrong (I don't write in c# and I might be missing something)
I also tried to find information about changes in *deps.json files in NET 6, but couldn't find it.
Please tell me if there are differences in deps.json for NET 5 and NET 6.
Best Regards, Dmitiry
@DmitriyLewen
My example clearly shows that the container is using version 6.0.922.41905 of System.Private.Uri not 4.3.0. Just because a version is in the .deps.json does not mean it the version actually in use. The *.deps.json method used by trivy may work for directly referenced packages but can't be used universally for everything in the *.deps.json. I am not familiar enough to suggest how this should work but the existing approach is definitely incorrect.
@DmitriyLewen - @jkone27 's situation is actually quite simillar to what @plaisted described. In his code he already uses latest of version of System.Private.Uri not 4.3.0. The 4.3.0 is coming from .deps.json due to the transitive dependency.
+1 to what @plaisted wrote, it would possibly better if trivy did filter out results coming from .deps.json inclusion to return the results tied to directly referenced packages.
okay, thanks! i understand what do you meant.
But what confuses me is that the *deps.json file does not include System.Private.Uri 6.0.922.41905.
Looks like NET6 includes this package as system and doesn't include this package to *.deps.json.
If it is true:
I am not sure if NET6 overwrite system packages from other dependencies.
i mean:
NET6 contains System.Private.Uri 6.0.922.41905
examplePackage uses System.Private.Uri 4.3
in this case: i am not sure if System.Private.Uri from examplePackage will be overwritten to 6.0.922.41905.
If examplePackage will still use System.Private.Uri 4.3 then examplePackage is vulnerable, because the wrong System.Private.Uri 4.3 package is used.
@pmuzyka-travix @plaisted What do you think about this?
@DmitriyLewen I don't know enough about the deps.json to suggest the best way to do this. You would need to get feedback from someone on the dotnet team.
A potential improvement to the current would be to check the if the file exists in the same folder as the deps.json file. That would let you know the file is being provided by the app instead of the runtime (although not foolproof as the loading behavior can be customized). I did experiment and published the same app using a self-contained deployment the assembly version of System.Private.Uri in the deps.json file was set to 6.0.0.0 and file version to 6.0.422.16404 so it appears that it will show the correct version if it is including it in the deployment. For assemblies the runtime is supposed to provide (non self-contained) it must put the lowest compatible version or something similar into the deps.json which is what is triggering the false positive from aqua.
I also noticed it tags a fileVersion to anything it includes under the targets section of the deps.json so that may be able to be used to filter out assemblies provided by the runtime (if no fileVersion given) and shouldn't be included in scans (assuming aqua validates the runtime version has no vulns).
There is an vulnerability reported by Microsoft (that is also discovered by Trivy) that explains how to detect if you need to update a transitive dependency:
https://github.com/advisories/GHSA-8g2p-5pqh-5jmc#:~:text=Discovering%20and%20fixing,the%20transitive%20dependency.
Thanks a look @JoostvdB94 I will check this.
Thanks @JoostvdB94 for this link.
I investigated this and i have some thoughts:
Perhaps your projects have multiple (more then one) dependencies with System.Private.Uri transitive dependency.
for example:
pkgA -> System.Private.Uri v4.3.0
pkgB -> System.Private.Uri v6.0.0
We think that NET 6 uses System.Private.Uri from pkgB but it uses lower version from pkgA (https://learn.microsoft.com/en-us/nuget/concepts/dependency-resolution#lowest-applicable-version).
@plaisted can i ask you to send me both of your test *.deps.json files? Also can you enable lock file and send me both lock files?(https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#enabling-the-lock-file) I want to explore these files. It will help me a lot.
Hey @DmitriyLewen thank you for investigating this.
I enabled the lock file and did not find any reference to System.Private.Uri. I did however find out that, although my application targets net6.0, it resolved the Microsoft.NETCore.App to 1.1.2 in the lockfile.
"Microsoft.NETCore.App": {
"type": "Transitive",
"resolved": "1.1.2",
"contentHash": "fcN0Ob6rjY7Zu0770cA5l9wRJvj7+ltJPPdryUidejkkhao+y2AYrtezBTlP9nCSFXLmYR9BtaknORT17x8reA==",
"dependencies": {...}
}
Microsoft.NETCore.App=1.1.2 was a dependency of another package:
"JsonDiffPatch": {
"type": "Transitive",
"resolved": "2.0.61",
"contentHash": "nZ4QtcU3jR+CBT69qcJBvCcWi5uKgPRrrvSMm4V8Z76ljJ/MFo1P55qXk/nQY0q0WC4v94m5qH4SDhovFfci+Q==",
"dependencies": {
"Microsoft.NETCore.App": "1.1.2",
"Newtonsoft.Json": "10.0.3"
}
},
When I build normally here is no System.Private.Uri.dll inside the output bin-folder. So I assume it uses the one that is installed globally on my machine.
However, when using a self-contained build (where all runtime dll's are included in the build result) I do see a System.Private.Uri file in the build output folder. That seems to be the 6.0.11 version.

hello @JoostvdB94 Thanks for your information
What about *.deps.json file?
Does it contain System.Private.Uri?
If yes, what version is used?
summary:
| build type | *deps.json contains System.Private.Uri | lock file contains System.Private.Uri | app folder contains System.Private.Uri.dll |
|---|---|---|---|
| normal | + | - | - |
| self-contained | + | - | + |
Is this summary right?
That's correct. It appears multiple times (in a self contained build output)
I've tried to isolate the JSON structure that's relevant. These are all occurrences of the search (search term was Private.Uri)
{
"targets": {
".NETCoreApp,Version=v6.0": {
"runtime.any.System.Runtime/4.3.0": {
"dependencies": {
"System.Private.Uri": "4.3.0"
}
},
"runtime.unix.System.Private.Uri/4.3.0": {
"dependencies": {
"runtime.native.System": "4.3.0"
}
},
"runtime.unix.System.Runtime.Extensions/4.3.0": {
"dependencies": {
"System.Private.Uri": "4.3.0",
"runtime.native.System": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2"
}
},
"System.Private.Uri/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "5.0.0",
"Microsoft.NETCore.Targets": "1.1.3",
"runtime.unix.System.Private.Uri": "4.3.0"
}
},
},
".NETCoreApp,Version=v6.0/alpine-x64": {
"runtimepack.Microsoft.NETCore.App.Runtime.linux-musl-x64/6.0.11": {
"runtime": {
"System.Private.Uri.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.1122.52304"
}
}
},
"runtime.any.System.Runtime/4.3.0": {
"dependencies": {
"System.Private.Uri": "4.3.0"
}
},
"runtime.unix.System.Private.Uri/4.3.0": {
"dependencies": {
"runtime.native.System": "4.3.0"
}
},
"runtime.unix.System.Runtime.Extensions/4.3.0": {
"dependencies": {
"System.Private.Uri": "4.3.0",
"runtime.native.System": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2"
}
},
"System.Private.Uri/4.3.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "5.0.0",
"Microsoft.NETCore.Targets": "1.1.3",
"runtime.unix.System.Private.Uri": "4.3.0"
}
},
}
},
"libraries": {
"runtime.unix.System.Private.Uri/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==",
"path": "runtime.unix.system.private.uri/4.3.0",
"hashPath": "runtime.unix.system.private.uri.4.3.0.nupkg.sha512"
},
"System.Private.Uri/4.3.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==",
"path": "system.private.uri/4.3.0",
"hashPath": "system.private.uri.4.3.0.nupkg.sha512"
},
}
}
Very strange that the lock file does not contain System.Private.Uri
It also doesn't have runtime.any.System.Runtime and runtime.unix.System.Runtime.Extensions?
UPD:
i installed dotnet add package runtime.unix.System.Runtime.Extensions --version 4.3.1 in my helloWorld project and lock file contains System.Private.Uri
UPD2:
I also see some pattern - perhaps the version from System.Private.Uri.dll is the NetCore version, not System.Private.Uri version.
The package.lock.json does contain "System.Runtime.Extensions": "4.3.0"
It does not contain runtime.any.System.Runtime or runtime.unix.System.Runtime.Extensions or System.Private.Uri
I also see some pattern - perhaps the version from System.Private.Uri.dll is the NetCore version, not System.Private.Uri version.
I believe that is true. System.Private.Uri is part of the NetCore runtime (thus the same version as NetCore?)
The package.lock.json does contain "System.Runtime.Extensions": "4.3.0" It does not contain runtime.any.System.Runtime or runtime.unix.System.Runtime.Extensions or System.Private.Uri
Hm... NET creates *.dll files (for these dependencies), so App uses these files. But lock file doesn't have these dependencies, which means App does not use them. It doesn't make sense... or we're missing something.
I think the lock file only specifies which packages it uses. Technically, the System.Private.Uri is not a package, as it is part of the dotnet runtime. That is why the .dll is present in self-contained builds, where the runtime does not need to be installed on the system that the app is running on, but the dll is missing in regular builds where the runtime needs to be installed on the system running the app.
In my opinion, we should treat both separately:
- Scan for vulnerabilities in packages
- Scan for vulnerabilities in the targeted framework version
The question then is: How would we separate those 2 checks?
The question then is: How would we separate those 2 checks?
As @plaisted mentioned: Maybe the solution to this is to indeed scan versions based on files included. This would work for both self-contained builds and the packages-only for regular builds:
I also noticed it tags a
fileVersionto anything it includes under thetargetssection of thedeps.jsonso that may be able to be used to filter out assemblies provided by the runtime (if no fileVersion given) and shouldn't be included in scans (assuming aqua validates the runtime version has no vulns).
For regular builds, we would need to check the files without a fileversion in order to include the vulnerabilities present in the runtime
Very strange that the lock file does not contain
System.Private.UriIt also doesn't haveruntime.any.System.Runtimeandruntime.unix.System.Runtime.Extensions?UPD: i installed
dotnet add package runtime.unix.System.Runtime.Extensions --version 4.3.1in my helloWorld project and lock file containsSystem.Private.UriUPD2: I also see some pattern - perhaps the version from
System.Private.Uri.dllis the NetCore version, notSystem.Private.Uriversion.
-
~The lock file is for direct / transitive package dependencies.
System.Private.Uriis part of the runtime not a direct / transitive dependency~. It does not have to be referenced in a project to be used. edit: it appears that this is incorrect and the lock file does include the runtime packages under some circumstances, see @DmitriyLewen comments below -
You shouldn't add those packages (including
System.Private.Uri) to a project. Going to nuget we see the description of the package isInternal implementation package not meant for direct consumption. Please do not reference directly. Provides implementation of System.Uri. -
The core of the issue is the
.deps.jsondoes not universally tell you what version is in the container or what version will be used when the app is executed but trivy is treating it that way. dotnet uses a combination of the.deps.jsonand what assemblies are available to determine what is actually used. You can validate this by modifying values in the.deps.jsonto non-existent versions (or even deleting the file) and the app will usually run fine. The current behavior is to add in version4.3.0to thedeps.jsonfor the dependencies included by the dotnet runtime for--self-contained falsepublished apps but I don't see that documented anywhere and may change. As I mentioned before an improvement would be to only look at data in thedeps.jsonthat has afileVersionbut I wasn't able to find documentation on when / why that is provided so may change as well.
Scan for vulnerabilities in the targeted framework version
I am not sure that is possible, because GitHub Advisory database uses package version(not framework version) in advisories.
e.g.
System.Private.Uri for CVE-2019-0980
Microsoft.Data.SqlClient and System.Data.SqlClient for CVE-2022-41064
As I mentioned before an improvement would be to only look at data in the deps.json that has a fileVersion but I wasn't able to find documentation on when / why that is provided so may change as well.
It looks like this is only possible way. I will create test PR with these changes.
I have installed several popular nuget packages, but my *deps.json file does not contain system/runtime packages.
@JoostvdB94 @plaisted If you have ability, can you play with your projects and try to find package that adds System.Private.Uri.
I'm starting to work with the changes and found a problem:
we will skip some of the dependencies from the libraries field.
This is bad - because users will ask: why Nuget includes these dependencies, but Trivy does not include them.
Also dependency name may not be the same as the name of the dll
e.g.
"runtimepack.Microsoft.NETCore.App.Runtime.linux-musl-x64/6.0.11": {
"runtime": {
"System.Private.Uri.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.1122.52304"
}
}
},
Or there are 2 dlls:
"Google.Apis.Auth/1.48.0": {
"dependencies": {
"Google.Apis": "1.48.0",
"Google.Apis.Core": "1.48.0"
},
"runtime": {
"lib/netstandard2.0/Google.Apis.Auth.PlatformServices.dll": {
"assemblyVersion": "1.48.0.0",
"fileVersion": "1.48.0.0"
},
"lib/netstandard2.0/Google.Apis.Auth.dll": {
"assemblyVersion": "1.48.0.0",
"fileVersion": "1.48.0.0"
}
}
},
Scan for vulnerabilities in the targeted framework version
I am not sure that is possible, because
GitHub Advisory databaseuses package version(not framework version) in advisories.
That nuget package is not meant to be installed separately (https://www.nuget.org/packages/System.Private.Uri/#:~:text=Please%20do%20not%20reference%20directly) Microsoft itself recommends installing a security update (https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2019-0980). This security update is not a single package, but the security update that applies to the runtime (https://catalog.update.microsoft.com/Search.aspx?q=KB4495618). So I still believe these packages are part of the runtime.
Why else is the only version that can be found (in the entire docker image) the runtime version that is located outside of the app installation folder? And how could a program actively use an older version if it is not present?
I have installed several popular nuget packages, but my
*deps.jsonfile does not contain system/runtime packages. @JoostvdB94 @plaisted If you have ability, can you play with your projects and try to find package that addsSystem.Private.Uri.
The package that causes it in my case targets netcore1.1: https://www.nuget.org/packages/JsonDiffPatch
@JoostvdB94 Perhaps i confused you. I meant that there is no information in the GitHub database that the framework has vulnerabilities (only in the description, but there are no rules for the description and we cannot parse it). Therefore, we cannot obtain information about vulnerabilities for frameworks.
The package that causes it in my case targets netcore1.1: https://www.nuget.org/packages/JsonDiffPatch
thanks for this!
I played with this package.
I think there is problem with dependencies of this package.
I installed JsonDiffPatch v2.0.61. After that my lock file contains System.Private.Uri and runtime packages.
...
"runtime.unix.System.Diagnostics.Debug": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==",
"dependencies": {
"runtime.native.System": "4.3.0"
}
},
...
"System.Private.Uri": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"runtime.unix.System.Private.Uri": "4.3.0"
}
},
...
As we said this is wrong logic.
As we said this is wrong logic.
I updated my statement to reflect your findings. Those must get added as transitive under some circumstances (maybe referencing .net framework / old net core packages?)
maybe referencing .net framework / old net core packages?
But this is still wrong way NET works:
Why does lock file and dll (when using --self-contained true) contain different dependency versions.
➜ cat packages.lock.json | grep '"System.Private.Uri": {' -A 9
"System.Private.Uri": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"runtime.unix.System.Private.Uri": "4.3.0"
}
},
➜ exiftool ./bin/release/net6.0/ubuntu.22.04-x64/System.Private.Uri.dll | grep Version
ExifTool Version Number : 12.40
Linker Version : 11.0
OS Version : 4.0
Image Version : 0.0
Subsystem Version : 4.0
File Version Number : 6.0.1022.47605
Product Version Number : 0.0.0.0
File Version : 6.0.1022.47605
Product Version : 6.0.10-servicing.22476.5+5a400c212afdf8e675c9a1d38442e6d2f19f7b74
Assembly Version : 6.0.0.0