cyclonedx-dotnet icon indicating copy to clipboard operation
cyclonedx-dotnet copied to clipboard

System.IO.InvalidDataException: Central Directory corrupt with 2.4.1

Open philipp-ranft opened this issue 2 years ago • 39 comments

Hi,

using version 2.4.1 some of our builds are failing due to a System.IO.InvalidDataException exception. Those builds were working using version 2.3.0 and are still working if we fix the version to 2.3.0. We observed this exception in two different projects for different dependencies:

Retrieving GitHub license for repository nspec/NSpec and ref master
Unhandled exception. System.IO.InvalidDataException: Central Directory corrupt.
 ---> System.IO.IOException: An attempt was made to move the position before the beginning of the stream.
   at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   --- End of inner exception stack trace ---
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   at System.IO.Compression.ZipArchive.Init(Stream stream, ZipArchiveMode mode, Boolean leaveOpen)
   at System.IO.Compression.ZipArchive..ctor(Stream stream, ZipArchiveMode mode, Boolean leaveOpen, Encoding entryNameEncoding)
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 315
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 315
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(String name, String version, Nullable`1 scope) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 231
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(NugetPackage nugetPackage) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 322
   at CycloneDX.Program.OnExecuteAsync(CommandLineApplication app) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 281
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.InvokeAsync(MethodInfo method, Object instance, Object[] arguments)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.OnExecute(ConventionContext context, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<>c__DisplayClass0_0.<<Apply>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync(String[] args, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync[TApp](CommandLineContext context, CancellationToken cancellationToken)
   at CycloneDX.Program.Main(String[] args) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 130
   at CycloneDX.Program.<Main>(String[] args)

and

Retrieving GitHub license for repository IdentityServer/IdentityServer3.AccessTokenValidation and ref master
Unhandled exception. System.IO.InvalidDataException: Central Directory corrupt.
 ---> System.IO.IOException: An attempt was made to move the position before the beginning of the stream.
   at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   --- End of inner exception stack trace ---
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   at System.IO.Compression.ZipArchive..ctor(Stream stream, ZipArchiveMode mode, Boolean leaveOpen, Encoding entryNameEncoding)
   at System.IO.Compression.ZipArchive..ctor(Stream stream, ZipArchiveMode mode, Boolean leaveOpen)
   at NuGet.Packaging.PackageArchiveReader..ctor(Stream stream, Boolean leaveStreamOpen, IFrameworkNameProvider frameworkProvider, IFrameworkCompatibilityProvider compatibilityProvider)
   at NuGet.Packaging.PackageArchiveReader..ctor(Stream stream)
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 273
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 279
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(String name, String version, Nullable`1 scope) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 231
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(NugetPackage nugetPackage) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 320
   at CycloneDX.Program.OnExecuteAsync(CommandLineApplication app) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 281
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.InvokeAsync(MethodInfo method, Object instance, Object[] arguments)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.OnExecute(ConventionContext context, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<>c__DisplayClass0_0.<<Apply>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync(String[] args, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync[TApp](CommandLineContext context, CancellationToken cancellationToken)
   at CycloneDX.Program.Main(String[] args) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 130
   at CycloneDX.Program.<Main>(String[] args)

The builds are running in Azure Pipelines on Linux Build Servers inside Docker containers based on mcr.microsoft.com/dotnet/sdk:3.1. We tried using mcr.microsoft.com/dotnet/sdk:6.0 as the container image but faced the same error message.

Thank you in advance!

philipp-ranft avatar Oct 14 '22 06:10 philipp-ranft

Only occured on the build server (Linux) for us. Worked on local Windows machines. Persisted with 2.5.1

tstaec avatar Oct 24 '22 13:10 tstaec

I am getting the same error with versions 2.5.1, 2.6.0, and 2.7.0

» Analyzing: /installkits/mspGisAMR/mspGisAMR.csproj
  Attempting to restore packages
  Packages restored
File not found: "/installkits/mspGisAMR/obj/project.assets.json", "/installkits/mspGisAMR/mspGisAMR.csproj"
  No packages found
Unhandled exception. System.IO.InvalidDataException: Central Directory corrupt.
 ---> System.IO.IOException: An attempt was made to move the position before the beginning of the stream.
   at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   --- End of inner exception stack trace ---
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   at System.IO.Compression.ZipArchive..ctor(Stream stream, ZipArchiveMode mode, Boolean leaveOpen, Encoding entryNameEncoding)
   at System.IO.Compression.ZipArchive..ctor(Stream stream, ZipArchiveMode mode, Boolean leaveOpen)
   at NuGet.Packaging.PackageArchiveReader..ctor(Stream stream, Boolean leaveStreamOpen, IFrameworkNameProvider frameworkProvider, IFrameworkCompatibilityProvider compatibilityProvider)
   at NuGet.Packaging.PackageArchiveReader..ctor(Stream stream)
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 273
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 279
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(String name, String version, Nullable`1 scope) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 157
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(NugetPackage nugetPackage) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 320
   at CycloneDX.Program.OnExecuteAsync(CommandLineApplication app) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 283
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.InvokeAsync(MethodInfo method, Object instance, Object[] arguments)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.OnExecute(ConventionContext context, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<>c__DisplayClass0_0.<<Apply>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync(String[] args, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync[TApp](CommandLineContext context, CancellationToken cancellationToken)
   at CycloneDX.Program.Main(String[] args) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 132
   at CycloneDX.Program.<Main>(String[] args)

Can't find out why this is happening

Gator8 avatar Dec 05 '22 21:12 Gator8

In my case, I use an internal NuGet repository for a dotnet restore for some internal packages.

In older versions I didn't need to specify a --url for cyclonedx as well, but after the 2.4.1 update I started to get this error across projects. I've been updating these projects to specify the NuGet url for our internal repository and they work again after that.

sam-gardiner avatar Dec 06 '22 09:12 sam-gardiner

oh wow. That lines up with what I'm seeing. I'll add the --url param and see what happens

Gator8 avatar Dec 06 '22 13:12 Gator8

This did not work for me. Even after setting the --url param, I still get the Central Directory corrupt message. The 2.3.0 docker image does work for me however. So, what's the difference between the 2.4.1 and 2.3.0 versions that would be causing this?

Gator8 avatar Dec 06 '22 15:12 Gator8

I was having this issue as well within an Azure build pipeline. Our solutions also rely on internal feeds, but supplying the feed in question did not solve the issue directly, although it was definitely a piece of the puzzle. I did however include a nuget restore step on the solution I was building the BOM for before executing the CycloneDX call and that alleviated the problem.

Just as a speculation it seems like this is maybe an issue with having a mix of PackageReference and package.config file usage in project files within a solution (as we do). If you follow the error, it's actually being thrown when constructing a ZipArchive object. Which is done directly in the constructor (ew IMO) of the PackageArchiveReader class in the NuGet.Packaging code (I believe this is part of the NuGet.Protocol package that CycloneDX is including). It's attempting to Read an archive based on the stream being set in. If I were to guess, the stream doesn't actually contain the content of the archive because the packages haven't been properly restored, and thus the failure.

I don't know for sure that's what's going on, but doing a restore + including the custom feed url seems to solve this problem for us.

praaymak avatar Dec 13 '22 16:12 praaymak

I'm having same issue on debian v11.5, dotnet SDK v6.0.0, cyclonedx-dotnet v2.7.0 and v2.6.0. Unhandled exception. System.IO.InvalidDataException: Central Directory corrupt.

cyclonedx-dotnet v2.3.0 does work for me.

Lzmog avatar Dec 19 '22 15:12 Lzmog

I'm having same with NuGet package source on windowns.

Retrieving GitHub license for repository starkbank/ecdsa-dotnet - URL: https://api.github.com/repos/starkbank/ecdsa-dotnet/license 
Unhandled exception. System.IO.InvalidDataException: Central Directory corrupt.
 ---> System.IO.IOException: An attempt was made to move the position before the beginning of the stream.
   at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   --- End of inner exception stack trace ---
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   at System.IO.Compression.ZipArchive..ctor(Stream stream, ZipArchiveMode mode, Boolean leaveOpen, Encoding entryNameEncoding)
   at System.IO.Compression.ZipArchive..ctor(Stream stream, ZipArchiveMode mode, Boolean leaveOpen)
   at NuGet.Packaging.PackageArchiveReader..ctor(Stream stream, Boolean leaveStreamOpen, IFrameworkNameProvider frameworkProvider, IFrameworkCompatibilityProvider compatibilityProvider)
   at NuGet.Packaging.PackageArchiveReader..ctor(Stream stream)
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 301
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 307
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(String name, String version, Nullable`1 scope) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 157
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(NugetPackage nugetPackage) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 348
   at CycloneDX.Program.OnExecuteAsync(CommandLineApplication app) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 293
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.InvokeAsync(MethodInfo method, Object instance, Object[] arguments)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.OnExecute(ConventionContext context, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<>c__DisplayClass0_0.<<Apply>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync(String[] args, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync[TApp](CommandLineContext context, CancellationToken cancellationToken)
   at CycloneDX.Program.Main(String[] args) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 138
   at CycloneDX.Program.<Main>(String[] args)

Cobra86 avatar Jan 26 '23 13:01 Cobra86

definetly requires a "dotnet restore" and additional url to the internal nuget repo. I am on v2.7.0.

@praaymak thanks for the hint!

So, if the project relies on internal / non-public nugets, cyclondx should give a warning when the --url parameter is missing.

mbxsuite avatar Feb 06 '23 16:02 mbxsuite

Same problem here with v2.7.0 on windows. Downgrading to v2.3.0 works.

DerHulk avatar Feb 23 '23 19:02 DerHulk

Same problem on Windows 2022 with version 2.7.0. Not using the github license scan

Found the following local nuget package cache locations:
    E:\Cache\NuGet\Packages

» Analyzing: E:\adoagents\agent3\_work\1102\s\src\project.csproj
Unhandled exception. System.IO.InvalidDataException: Central Directory corrupt.
 ---> System.IO.IOException: An attempt was made to move the position before the beginning of the stream.
   at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   --- End of inner exception stack trace ---
   at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory()
   at System.IO.Compression.ZipArchive..ctor(Stream stream, ZipArchiveMode mode, Boolean leaveOpen, Encoding entryNameEncoding)
   at System.IO.Compression.ZipArchive..ctor(Stream stream, ZipArchiveMode mode, Boolean leaveOpen)
   at NuGet.Packaging.PackageArchiveReader..ctor(Stream stream, Boolean leaveStreamOpen, IFrameworkNameProvider frameworkProvider, IFrameworkCompatibilityProvider compatibilityProvider)
   at NuGet.Packaging.PackageArchiveReader..ctor(Stream stream)
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 301
   at CycloneDX.Services.NugetV3Service.GetNuspec(String name, String version, String nuspecFilename, FindPackageByIdResource resource) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 307
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(String name, String version, Nullable`1 scope) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 157
   at CycloneDX.Services.NugetV3Service.GetComponentAsync(NugetPackage nugetPackage) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Services/NugetV3Service.cs:line 348
   at CycloneDX.Program.OnExecuteAsync(CommandLineApplication app) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 293
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.InvokeAsync(MethodInfo method, Object instance, Object[] arguments)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.OnExecute(ConventionContext context, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<>c__DisplayClass0_0.<<Apply>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync(String[] args, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync[TApp](CommandLineContext context, CancellationToken cancellationToken)
   at CycloneDX.Program.Main(String[] args) in /home/runner/work/cyclonedx-dotnet/cyclonedx-dotnet/CycloneDX/Program.cs:line 138
   at CycloneDX.Program.<Main>(String[] args)

peterbarendse avatar Feb 24 '23 15:02 peterbarendse

Can confirm @peterbarendse, seeing the same behaviour.

pkoelemij avatar Feb 27 '23 08:02 pkoelemij

Did anyone figure out solution for using version 2.7.0 ? I am facing this issue if I run it in Linux VM in azure pipelines as well as local machine but it is working without any issues in my local windows machine, not sure what causing the issue. I also tried to run in windows VMs in azure pipelines, still causing same issue, not sure how it is working locally with windows machine. Did anyone face the similar issue ? Unhandled exception. System.IO.InvalidDataException: Central Directory corrupt. ---> System.IO.IOException: An attempt was made to move the position before the beginning of the stream. at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc) at System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory() --- End of inner exception stack trace ---

gkrishna240988 avatar Mar 07 '23 05:03 gkrishna240988

I have the same error message, and dug some deeper. CycloneDX tries to load the nuspec file from the caches, which succeeds most of the time. If the nuspec file is not in the expected location, it tries to load the nupkg from the web and fails with the ZipArchive error if loading fails.

I found a few reasons why this nuspec might not be found in the cache.

  1. It appears that some packages carry multiple version number formats. For example packages CuttingEdge.Conditions version 1.2.0 is referenced in packages.config as version 1.2.0.0 . CycloneDX expects this longer version, but it doesn't find the nuspec at C:\Users....nuget\packages\cuttingedge.conditions\1.2.0.0\cuttingedge.conditions.nuspec because the path uses the shorter version number. According to https://learn.microsoft.com/en-us/nuget/concepts/package-versioning#normalized-version-numbers , "a zero in the fourth part of the version number will be omitted".
  2. Nuget restore (if in your build pipeline before the CycloneDX step) might put the packages in packages folder in the solution, and that's not where CycloneDX searches.

If your packages are from nuget.org, and CycloneDX can retrieve the packages, it can work around this condition. And then you don't see any error, just a delay.

Regarding reason number 2 above: in method DotnetUtilsService.GetPackageCachePaths I added .\packages to the list of cache folders to search, and then it successfully loaded the packages. Is that the right solution direction?

Arthur-van-Dongen avatar Mar 31 '23 15:03 Arthur-van-Dongen

I have the same error message, and dug some deeper. CycloneDX tries to load the nuspec file from the caches, which succeeds most of the time. If the nuspec file is not in the expected location, it tries to load the nupkg from the web and fails with the ZipArchive error if loading fails.

I found a few reasons why this nuspec might not be found in the cache.

  1. It appears that some packages carry multiple version number formats. For example packages CuttingEdge.Conditions version 1.2.0 is referenced in packages.config as version 1.2.0.0 . CycloneDX expects this longer version, but it doesn't find the nuspec at C:\Users....nuget\packages\cuttingedge.conditions\1.2.0.0\cuttingedge.conditions.nuspec because the path uses the shorter version number. According to https://learn.microsoft.com/en-us/nuget/concepts/package-versioning#normalized-version-numbers , "a zero in the fourth part of the version number will be omitted".
  2. Nuget restore (if in your build pipeline before the CycloneDX step) might put the packages in packages folder in the solution, and that's not where CycloneDX searches.

If your packages are from nuget.org, and CycloneDX can retrieve the packages, it can work around this condition. And then you don't see any error, just a delay.

Regarding reason number 2 above: in method DotnetUtilsService.GetPackageCachePaths I added .\packages to the list of cache folders to search, and then it successfully loaded the packages. Is that the right solution direction?

I like this solution but i like the ability to pass in a cache path much better. We override the default, which is a .NET provided functionality, and it looks like we'll have to work around this by copying our packages to the default package cache location if this isn't offered. (or we can try downgrading it looks like)

msherms2 avatar Apr 25 '23 22:04 msherms2

We override the default, which is a .NET provided functionality, and it looks like we'll have to work around this by copying our packages to the default package cache location if this isn't offered. (or we can try downgrading it looks like)

CycloneDX-dotnet gets the cache paths using command "dotnet nuget locals global-packages --list" . According to https://learn.microsoft.com/en-us/nuget/consume-packages/managing-the-global-packages-and-cache-folders the global-packages cache location can be controlled through the nuget config file or environment variable. I guess you should be able to point the tool to your own cache this way.

Arthur-van-Dongen avatar May 04 '23 08:05 Arthur-van-Dongen

We override the default, which is a .NET provided functionality, and it looks like we'll have to work around this by copying our packages to the default package cache location if this isn't offered. (or we can try downgrading it looks like)

CycloneDX-dotnet gets the cache paths using command "dotnet nuget locals global-packages --list" . According to https://learn.microsoft.com/en-us/nuget/consume-packages/managing-the-global-packages-and-cache-folders the global-packages cache location can be controlled through the nuget config file or environment variable. I guess you should be able to point the tool to your own cache this way.

Arthur,

Ah, great find, I took a look at the code but not deep enough to notice where it obtains that. We'll give that a shot, we should be able to obtain that cache programmatically and then use above to set it into our file before nuget restore. Much better than copying stuff around! Thanks!

-Matt

msherms2 avatar May 04 '23 12:05 msherms2

We override the default, which is a .NET provided functionality, and it looks like we'll have to work around this by copying our packages to the default package cache location if this isn't offered. (or we can try downgrading it looks like)

CycloneDX-dotnet gets the cache paths using command "dotnet nuget locals global-packages --list" . According to https://learn.microsoft.com/en-us/nuget/consume-packages/managing-the-global-packages-and-cache-folders the global-packages cache location can be controlled through the nuget config file or environment variable. I guess you should be able to point the tool to your own cache this way.

Arthur,

Ah, great find, I took a look at the code but not deep enough to notice where it obtains that. We'll give that a shot, we should be able to obtain that cache programmatically and then use above to set it into our file before nuget restore. Much better than copying stuff around! Thanks!

-Matt

Confirmed! This was a great work around, thanks again Arthur!

msherms2 avatar May 08 '23 12:05 msherms2

Same issue here. Setup: Azure DevOps Pipeline, private azure devops Nuget Feed. I do have a dotnet restore step before the cyclonedx step which works fine. however, with newer version it was necessary to provide a --url with the private nuget feed. User/pw was not necessary somehow.

I wonder why it does not pick that up from a nuget config file which is also available containing the URL?

rkg-mm avatar Oct 23 '23 17:10 rkg-mm

I could reproduce the exception by using a package from a private repository and removing it from the cache folder before running CycloneDX. However, adding(in my case) -u http://localhost:8081/repository/nuget-group/index.json solved the problem.

Normally you would have everything in the cache after running restore, but it is possible that restore and CycloneDX run in different containers. It seems the nuget library does not automatically read the sources from the config; this might be a potential code change.

Another potential code change would be a custom exception, pointing the user towards providing the -u parameter.

If there is still anyone who get this error even with -u, please come forward.

mtsfoni avatar Dec 30 '23 16:12 mtsfoni

I could reproduce the exception by using a package from a private repository and removing it from the cache folder before running CycloneDX. However, adding(in my case) -u http://localhost:8081/repository/nuget-group/index.json solved the problem.

Normally you would have everything in the cache after running restore, but it is possible that restore and CycloneDX run in different containers. It seems the nuget library does not automatically read the sources from the config; this might be a potential code change.

Another potential code change would be a custom exception, pointing the user towards providing the -u parameter.

If there is still anyone who get this error even with -u, please come forward.

Are you saying that you solved this by using -u <Path to your local feed> and this made needing a cache not needed? This is even more desirable a fix because we do containerize our Cyclone DX usage. It would be ideal for us to be able to either restore directly on demand, or just point it to a gathering of the packages we stashed. Please confirm if -u option is doing what I think it is. Thanks!

msherms2 avatar Jan 02 '24 15:01 msherms2

Are you saying that you solved this by using -u <Path to your local feed> and this made needing a cache not needed?

It's the other way around. --URL is used as fallback, when the package cannot be found in the cache. Which is usually the case, when restore run on another system (e.g. container) and cyclonedx runs with --disable-package-restore. The "Central Directory Corrupt"-Error indicates that the package couldn't be found in the repository.

-u <Path to your local feed>

No idea if NuGet knows how to handle a path here - often it does. I use a URL. Do you only have a local feed as path and no private NuGet Repository (eg. Nexus) as URL as in my example?

Please confirm if -u option is doing what I think it is. Thanks!

To conclude: If information for a package is not found in the NuGet Cache, then CycloneDX will try to get the information from a NuGet feed. By default, it will try the public Microsoft feed. If -u is set, it tries to query a feed at the given URL.

Please let me know whether that helps you.

mtsfoni avatar Jan 02 '24 19:01 mtsfoni

I think that might work for our purposes, I'd love to give it a shot, I'll check if it works. Yes, we use a local directory because we stash the packages we have already fetched in an earlier stage, so we should be able to just point it to there. I'll try to get back next week when I can have a chance to try something. Thanks for the info!

msherms2 avatar Jan 02 '24 21:01 msherms2

The problem is because because of GetNuspec C:\Repos\cyclonedx-dotnet\CycloneDX\Services\NugetV3Service.cs

>	System.Private.CoreLib.dll!System.IO.MemoryStream.Seek(long offset, System.IO.SeekOrigin loc) Line 476	C#
 	System.IO.Compression.dll!System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory() Line 352	C#
 	System.IO.Compression.dll!System.IO.Compression.ZipArchive.ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen, System.Text.Encoding entryNameEncoding) Line 179	C#
 	System.IO.Compression.dll!System.IO.Compression.ZipArchive.ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen) Line 106	C#
 	NuGet.Packaging.dll!NuGet.Packaging.PackageArchiveReader.PackageArchiveReader(System.IO.Stream stream, bool leaveStreamOpen, NuGet.Frameworks.IFrameworkNameProvider frameworkProvider, NuGet.Frameworks.IFrameworkCompatibilityProvider compatibilityProvider)	Unknown
 	NuGet.Packaging.dll!NuGet.Packaging.PackageArchiveReader.PackageArchiveReader(System.IO.Stream stream)	Unknown
 	CycloneDX.dll!CycloneDX.Services.NugetV3Service.GetNuspec(string name, string version, string nuspecFilename, NuGet.Protocol.Core.Types.FindPackageByIdResource resource) Line 325	C#

fbrunetgirard avatar Mar 25 '24 10:03 fbrunetgirard

The problem is because because of GetNuspec C:\Repos\cyclonedx-dotnet\CycloneDX\Services\NugetV3Service.cs

>	System.Private.CoreLib.dll!System.IO.MemoryStream.Seek(long offset, System.IO.SeekOrigin loc) Line 476	C#
 	System.IO.Compression.dll!System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory() Line 352	C#
 	System.IO.Compression.dll!System.IO.Compression.ZipArchive.ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen, System.Text.Encoding entryNameEncoding) Line 179	C#
 	System.IO.Compression.dll!System.IO.Compression.ZipArchive.ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen) Line 106	C#
 	NuGet.Packaging.dll!NuGet.Packaging.PackageArchiveReader.PackageArchiveReader(System.IO.Stream stream, bool leaveStreamOpen, NuGet.Frameworks.IFrameworkNameProvider frameworkProvider, NuGet.Frameworks.IFrameworkCompatibilityProvider compatibilityProvider)	Unknown
 	NuGet.Packaging.dll!NuGet.Packaging.PackageArchiveReader.PackageArchiveReader(System.IO.Stream stream)	Unknown
 	CycloneDX.dll!CycloneDX.Services.NugetV3Service.GetNuspec(string name, string version, string nuspecFilename, NuGet.Protocol.Core.Types.FindPackageByIdResource resource) Line 325	C#

@fbrunetgirard After all the editing there is not much left of your response. Are you saying it worked in your case when you changed the MemorySteam to a FileStream?

mtsfoni avatar Mar 25 '24 12:03 mtsfoni

The problem is because because of GetNuspec C:\Repos\cyclonedx-dotnet\CycloneDX\Services\NugetV3Service.cs

>	System.Private.CoreLib.dll!System.IO.MemoryStream.Seek(long offset, System.IO.SeekOrigin loc) Line 476	C#
 	System.IO.Compression.dll!System.IO.Compression.ZipArchive.ReadEndOfCentralDirectory() Line 352	C#
 	System.IO.Compression.dll!System.IO.Compression.ZipArchive.ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen, System.Text.Encoding entryNameEncoding) Line 179	C#
 	System.IO.Compression.dll!System.IO.Compression.ZipArchive.ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen) Line 106	C#
 	NuGet.Packaging.dll!NuGet.Packaging.PackageArchiveReader.PackageArchiveReader(System.IO.Stream stream, bool leaveStreamOpen, NuGet.Frameworks.IFrameworkNameProvider frameworkProvider, NuGet.Frameworks.IFrameworkCompatibilityProvider compatibilityProvider)	Unknown
 	NuGet.Packaging.dll!NuGet.Packaging.PackageArchiveReader.PackageArchiveReader(System.IO.Stream stream)	Unknown
 	CycloneDX.dll!CycloneDX.Services.NugetV3Service.GetNuspec(string name, string version, string nuspecFilename, NuGet.Protocol.Core.Types.FindPackageByIdResource resource) Line 325	C#

@fbrunetgirard After all the editing there is not much left of your response. Are you saying it worked in your case when you changed the MemorySteam to a FileStream?

Im trying to test more im still not sure how to figure out if this is because of a private nuget feed or not The memory stream to file doesnt give me good result yet, since it empty, at least im able to reproduce it

    FileStream file = new FileStream(path, FileMode.CreateNew);
    packageStream.WriteTo(file);
    file.Close();

fbrunetgirard avatar Mar 25 '24 12:03 fbrunetgirard

Some packages cannot be found inside my private nuget repo (proget) and crash the tool but they are from nuget.org It was worst when i did not use the -u argument and im using -dpr

So far it doesnt seem to read nuget.config file as well

fbrunetgirard avatar Mar 26 '24 15:03 fbrunetgirard

I merged those PRs from Dependabot yesterday. There is one issue I want to fix and then I will release a new version. Hopefully this is solved then. I'd appreciate a short feedback after.

mtsfoni avatar Mar 27 '24 13:03 mtsfoni

I merged those PRs from Dependabot yesterday. There is one issue I want to fix and then I will release a new version. Hopefully this is solved then. I'd appreciate a short feedback after.

Great thanks!

Still invalid package can mess the whole thing up, or when the private feed is not link to nuget.org Nuget.config will be great to be use instead of specifying one nuget url only

Files doesnt seem cached as well when calling cyclonedx multiple time or same projects have the same reference.

fbrunetgirard avatar Mar 27 '24 13:03 fbrunetgirard

I done more investigation and the package is found using the cmd

$Username = 'MyUsername'
$Password = ConvertTo-SecureString 'password' -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential($Username, $Password)
$package = "jQuery.vsdoc"
$version = "1.6"
Find-Package $package -RequiredVersion $version -Source 'myrepo' -Credential $Credential

Name Version Source Summary


jQuery.vsdoc 1.6 MSNUGET vsdoc files for Visual Studio IntelliS...

But crashing using the sdk `` `using NuGet.Common; using NuGet.Configuration; using NuGet.Packaging; using NuGet.Protocol; using NuGet.Protocol.Core.Types; using NuGet.Versioning;

string url = "url"; string username = "username"; string password = "password"; ILogger logger = NullLogger.Instance; CancellationToken cancellationToken = CancellationToken.None;

SourceCacheContext cache = new SourceCacheContext();

PackageSource packageSource = new PackageSource(url); packageSource.Credentials = new PackageSourceCredential(url,username, password, true, null);

SourceRepository repository = Repository.Factory.GetCoreV3(packageSource); FindPackageByIdResource resource = await repository.GetResourceAsync<FindPackageByIdResource>();

string packageId = "jQuery.vsdoc"; NuGetVersion packageVersion = new NuGetVersion("1.6"); using MemoryStream packageStream = new MemoryStream();

await resource.CopyNupkgToStreamAsync( packageId, packageVersion, packageStream, cache, logger, cancellationToken);

Console.WriteLine($"Downloaded package {packageId} {packageVersion}");

using PackageArchiveReader packageReader = new PackageArchiveReader(packageStream); NuspecReader nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken);`

fbrunetgirard avatar Mar 27 '24 15:03 fbrunetgirard