dependabot-nuget 0.286.0 → 0.287.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -729,6 +729,191 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
729
729
  );
730
730
  }
731
731
 
732
+ [Fact]
733
+ public async Task AnalysisCanContineWhenRegistrationJSONIsMalformed()
734
+ {
735
+ // from a case seen in the wild; a transitive dependency's registration JSON has an invalid `range` property
736
+ // analysis should continue
737
+ var aspNetCoreAppRefPackage = MockNuGetPackage.WellKnownReferencePackage("Microsoft.AspNetCore.App", "net8.0");
738
+ var desktopAppRefPackage = MockNuGetPackage.WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net8.0");
739
+ var netCoreAppRefPackage = MockNuGetPackage.WellKnownReferencePackage("Microsoft.NETCore.App", "net8.0",
740
+ [
741
+ ("data/FrameworkList.xml", Encoding.UTF8.GetBytes("""
742
+ <FileList TargetFrameworkIdentifier=".NETCoreApp" TargetFrameworkVersion="8.0" FrameworkName="Microsoft.NETCore.App" Name=".NET Runtime">
743
+ </FileList>
744
+ """))
745
+ ]);
746
+ (int, byte[]) TestHttpHandler(string uriString)
747
+ {
748
+ var uri = new Uri(uriString, UriKind.Absolute);
749
+ var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
750
+ switch (uri.PathAndQuery)
751
+ {
752
+ // initial request is good
753
+ case "/index.json":
754
+ return (200, Encoding.UTF8.GetBytes($$"""
755
+ {
756
+ "version": "3.0.0",
757
+ "resources": [
758
+ {
759
+ "@id": "{{baseUrl}}/download",
760
+ "@type": "PackageBaseAddress/3.0.0"
761
+ },
762
+ {
763
+ "@id": "{{baseUrl}}/query",
764
+ "@type": "SearchQueryService"
765
+ },
766
+ {
767
+ "@id": "{{baseUrl}}/registrations",
768
+ "@type": "RegistrationsBaseUrl"
769
+ }
770
+ ]
771
+ }
772
+ """));
773
+ case "/registrations/some.package/index.json":
774
+ return (200, Encoding.UTF8.GetBytes("""
775
+ {
776
+ "count": 1,
777
+ "items": [
778
+ {
779
+ "lower": "1.0.0",
780
+ "upper": "1.1.0",
781
+ "items": [
782
+ {
783
+ "catalogEntry": {
784
+ "listed": true,
785
+ "version": "1.0.0"
786
+ }
787
+ },
788
+ {
789
+ "catalogEntry": {
790
+ "listed": true,
791
+ "version": "1.1.0",
792
+ "dependencyGroups": [
793
+ {
794
+ "dependencies": [
795
+ {
796
+ "id": "Some.Transitive.Dependency",
797
+ "range": "",
798
+ "comment": "The above range is invalid and fails the JSON parse"
799
+ }
800
+ ]
801
+ }
802
+ ]
803
+ }
804
+ }
805
+ ]
806
+ }
807
+ ]
808
+ }
809
+ """));
810
+ case "/download/some.package/index.json":
811
+ return (200, Encoding.UTF8.GetBytes("""
812
+ {
813
+ "versions": [
814
+ "1.0.0",
815
+ "1.1.0"
816
+ ]
817
+ }
818
+ """));
819
+ case "/download/some.package/1.0.0/some.package.1.0.0.nupkg":
820
+ return (200, MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0").GetZipStream().ReadAllBytes());
821
+ case "/download/some.package/1.1.0/some.package.1.1.0.nupkg":
822
+ return (200, MockNuGetPackage.CreateSimplePackage("Some.Package", "1.1.0", "net8.0").GetZipStream().ReadAllBytes());
823
+ case "/download/microsoft.aspnetcore.app.ref/index.json":
824
+ return (200, Encoding.UTF8.GetBytes($$"""
825
+ {
826
+ "versions": [
827
+ "{{aspNetCoreAppRefPackage.Version}}"
828
+ ]
829
+ }
830
+ """));
831
+ case "/download/microsoft.netcore.app.ref/index.json":
832
+ return (200, Encoding.UTF8.GetBytes($$"""
833
+ {
834
+ "versions": [
835
+ "{{netCoreAppRefPackage.Version}}"
836
+ ]
837
+ }
838
+ """));
839
+ case "/download/microsoft.windowsdesktop.app.ref/index.json":
840
+ return (200, Encoding.UTF8.GetBytes($$"""
841
+ {
842
+ "versions": [
843
+ "{{desktopAppRefPackage.Version}}"
844
+ ]
845
+ }
846
+ """));
847
+ default:
848
+ if (uri.PathAndQuery == $"/download/microsoft.aspnetcore.app.ref/{aspNetCoreAppRefPackage.Version}/microsoft.aspnetcore.app.ref.{aspNetCoreAppRefPackage.Version}.nupkg")
849
+ {
850
+ return (200, aspNetCoreAppRefPackage.GetZipStream().ReadAllBytes());
851
+ }
852
+
853
+ if (uri.PathAndQuery == $"/download/microsoft.netcore.app.ref/{netCoreAppRefPackage.Version}/microsoft.netcore.app.ref.{netCoreAppRefPackage.Version}.nupkg")
854
+ {
855
+ return (200, netCoreAppRefPackage.GetZipStream().ReadAllBytes());
856
+ }
857
+
858
+ if (uri.PathAndQuery == $"/download/microsoft.windowsdesktop.app.ref/{desktopAppRefPackage.Version}/microsoft.windowsdesktop.app.ref.{desktopAppRefPackage.Version}.nupkg")
859
+ {
860
+ return (200, desktopAppRefPackage.GetZipStream().ReadAllBytes());
861
+ }
862
+
863
+ // nothing else is found
864
+ return (404, Encoding.UTF8.GetBytes("{}"));
865
+ };
866
+ }
867
+ using var http = TestHttpServer.CreateTestServer(TestHttpHandler);
868
+ await TestAnalyzeAsync(
869
+ extraFiles:
870
+ [
871
+ ("NuGet.Config", $"""
872
+ <configuration>
873
+ <packageSources>
874
+ <clear />
875
+ <add key="package_feed" value="{http.BaseUrl.TrimEnd('/')}/index.json" allowInsecureConnections="true" />
876
+ </packageSources>
877
+ </configuration>
878
+ """)
879
+ ],
880
+ discovery: new()
881
+ {
882
+ Path = "/",
883
+ Projects =
884
+ [
885
+ new()
886
+ {
887
+ FilePath = "./project.csproj",
888
+ TargetFrameworks = ["net8.0"],
889
+ Dependencies =
890
+ [
891
+ new("Some.Package", "1.0.0", DependencyType.PackageReference),
892
+ ]
893
+ }
894
+ ]
895
+ },
896
+ dependencyInfo: new()
897
+ {
898
+ Name = "Some.Package",
899
+ Version = "1.0.0",
900
+ IgnoredVersions = [],
901
+ IsVulnerable = false,
902
+ Vulnerabilities = [],
903
+ },
904
+ expectedResult: new()
905
+ {
906
+ CanUpdate = true,
907
+ UpdatedVersion = "1.1.0",
908
+ VersionComesFromMultiDependencyProperty = false,
909
+ UpdatedDependencies =
910
+ [
911
+ new("Some.Package", "1.1.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
912
+ ],
913
+ }
914
+ );
915
+ }
916
+
732
917
  [Fact]
733
918
  public async Task ResultFileHasCorrectShapeForAuthenticationFailure()
734
919
  {
@@ -835,4 +1020,121 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
835
1020
  }
836
1021
  );
837
1022
  }
1023
+
1024
+ [Fact]
1025
+ public async Task AnalysisFailsWhenNewerPackageDownloadIsDenied()
1026
+ {
1027
+ static (int, byte[]) TestHttpHandler(string uriString)
1028
+ {
1029
+ var uri = new Uri(uriString, UriKind.Absolute);
1030
+ var baseUrl = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
1031
+ return uri.PathAndQuery switch
1032
+ {
1033
+ // initial request is good
1034
+ "/index.json" => (200, Encoding.UTF8.GetBytes($$"""
1035
+ {
1036
+ "version": "3.0.0",
1037
+ "resources": [
1038
+ {
1039
+ "@id": "{{baseUrl}}/download",
1040
+ "@type": "PackageBaseAddress/3.0.0"
1041
+ },
1042
+ {
1043
+ "@id": "{{baseUrl}}/query",
1044
+ "@type": "SearchQueryService"
1045
+ },
1046
+ {
1047
+ "@id": "{{baseUrl}}/registrations",
1048
+ "@type": "RegistrationsBaseUrl"
1049
+ }
1050
+ ]
1051
+ }
1052
+ """)),
1053
+ // request for package index is good
1054
+ "/registrations/some.package/index.json" => (200, Encoding.UTF8.GetBytes("""
1055
+ {
1056
+ "count": 1,
1057
+ "items": [
1058
+ {
1059
+ "lower": "1.0.0",
1060
+ "upper": "1.1.0",
1061
+ "items": [
1062
+ {
1063
+ "catalogEntry": {
1064
+ "listed": true,
1065
+ "version": "1.0.0"
1066
+ }
1067
+ },
1068
+ {
1069
+ "catalogEntry": {
1070
+ "listed": true,
1071
+ "version": "1.1.0"
1072
+ }
1073
+ }
1074
+ ]
1075
+ }
1076
+ ]
1077
+ }
1078
+ """)),
1079
+ // request for versions is good
1080
+ "/download/some.package/index.json" => (200, Encoding.UTF8.GetBytes("""
1081
+ {
1082
+ "versions": [
1083
+ "1.0.0",
1084
+ "1.1.0"
1085
+ ]
1086
+ }
1087
+ """)),
1088
+ // download of old package is good
1089
+ "/download/some.package/1.0.0/some.package.1.0.0.nupkg" => (200, MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net9.0").GetZipStream().ReadAllBytes()),
1090
+ // download of new package is denied
1091
+ "/download/some.package/1.1.0/some.package.1.1.0.nupkg" => (401, Array.Empty<byte>()),
1092
+ // all other requests are not found
1093
+ _ => (404, Encoding.UTF8.GetBytes("{}")),
1094
+ };
1095
+ }
1096
+ using var http = TestHttpServer.CreateTestServer(TestHttpHandler);
1097
+ await TestAnalyzeAsync(
1098
+ extraFiles:
1099
+ [
1100
+ ("NuGet.Config", $"""
1101
+ <configuration>
1102
+ <packageSources>
1103
+ <clear />
1104
+ <add key="private_feed" value="{http.BaseUrl.TrimEnd('/')}/index.json" allowInsecureConnections="true" />
1105
+ </packageSources>
1106
+ </configuration>
1107
+ """)
1108
+ ],
1109
+ discovery: new()
1110
+ {
1111
+ Path = "/",
1112
+ Projects = [
1113
+ new()
1114
+ {
1115
+ FilePath = "./project.csproj",
1116
+ TargetFrameworks = ["net9.0"],
1117
+ Dependencies = [
1118
+ new("Some.Package", "1.0.0", DependencyType.PackageReference),
1119
+ ],
1120
+ }
1121
+ ]
1122
+ },
1123
+ dependencyInfo: new()
1124
+ {
1125
+ Name = "Some.Package",
1126
+ Version = "1.0.0",
1127
+ IgnoredVersions = [],
1128
+ IsVulnerable = false,
1129
+ Vulnerabilities = [],
1130
+ },
1131
+ expectedResult: new()
1132
+ {
1133
+ UpdatedVersion = "1.0.0",
1134
+ CanUpdate = false,
1135
+ VersionComesFromMultiDependencyProperty = false,
1136
+ UpdatedDependencies = [],
1137
+ }
1138
+ );
1139
+ }
838
1140
  }
@@ -107,6 +107,106 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
107
107
  );
108
108
  }
109
109
 
110
+ [Fact]
111
+ public async Task TestDependenciesSeparatedBySemicolon()
112
+ {
113
+ await TestDiscoveryAsync(
114
+ packages:
115
+ [
116
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"),
117
+ MockNuGetPackage.CreateSimplePackage("Some.Package2", "9.0.1", "net8.0"),
118
+ ],
119
+ workspacePath: "src",
120
+ files: new[]
121
+ {
122
+ ("src/project.csproj", """
123
+ <Project Sdk="Microsoft.NET.Sdk">
124
+ <PropertyGroup>
125
+ <TargetFramework>net8.0</TargetFramework>
126
+ <SomePackageVersion>9.0.1</SomePackageVersion>
127
+ </PropertyGroup>
128
+
129
+ <ItemGroup>
130
+ <PackageReference Include="Some.Package;Some.Package2" Version="$(SomePackageVersion)" />
131
+ </ItemGroup>
132
+ </Project>
133
+ """)
134
+ },
135
+ expectedResult: new()
136
+ {
137
+ Path = "src",
138
+ Projects = [
139
+ new()
140
+ {
141
+ FilePath = "project.csproj",
142
+ TargetFrameworks = ["net8.0"],
143
+ ReferencedProjectPaths = [],
144
+ ExpectedDependencyCount = 3,
145
+ Dependencies = [
146
+ new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk),
147
+ new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
148
+ new("Some.Package2", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
149
+ ],
150
+ Properties = [
151
+ new("SomePackageVersion", "9.0.1", "src/project.csproj"),
152
+ new("TargetFramework", "net8.0", "src/project.csproj"),
153
+ ]
154
+ }
155
+ ]
156
+ }
157
+ );
158
+ }
159
+
160
+ [Fact]
161
+ public async Task TestDependenciesSeparatedBySemicolonWithWhitespace()
162
+ {
163
+ await TestDiscoveryAsync(
164
+ packages:
165
+ [
166
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"),
167
+ MockNuGetPackage.CreateSimplePackage("Some.Package2", "9.0.1", "net8.0"),
168
+ ],
169
+ workspacePath: "src",
170
+ files: new[]
171
+ {
172
+ ("src/project.csproj", """
173
+ <Project Sdk="Microsoft.NET.Sdk">
174
+ <PropertyGroup>
175
+ <TargetFramework>net8.0</TargetFramework>
176
+ <SomePackageVersion>9.0.1</SomePackageVersion>
177
+ </PropertyGroup>
178
+
179
+ <ItemGroup>
180
+ <PackageReference Include=" Some.Package ; Some.Package2 " Version="$(SomePackageVersion)" />
181
+ </ItemGroup>
182
+ </Project>
183
+ """)
184
+ },
185
+ expectedResult: new()
186
+ {
187
+ Path = "src",
188
+ Projects = [
189
+ new()
190
+ {
191
+ FilePath = "project.csproj",
192
+ TargetFrameworks = ["net8.0"],
193
+ ReferencedProjectPaths = [],
194
+ ExpectedDependencyCount = 3,
195
+ Dependencies = [
196
+ new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk),
197
+ new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
198
+ new("Some.Package2", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true),
199
+ ],
200
+ Properties = [
201
+ new("SomePackageVersion", "9.0.1", "src/project.csproj"),
202
+ new("TargetFramework", "net8.0", "src/project.csproj"),
203
+ ]
204
+ }
205
+ ]
206
+ }
207
+ );
208
+ }
209
+
110
210
  [Fact]
111
211
  public async Task TestPackageConfig()
112
212
  {
@@ -375,6 +475,175 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase
375
475
  );
376
476
  }
377
477
 
478
+ [Fact]
479
+ public async Task TestRepo_SolutionFileCasingMismatchIsResolved()
480
+ {
481
+ var solutionPath = "solution.sln";
482
+ await TestDiscoveryAsync(
483
+ packages:
484
+ [
485
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"),
486
+ ],
487
+ workspacePath: "",
488
+ files: new[]
489
+ {
490
+ ("src/project.csproj", """
491
+ <Project Sdk="Microsoft.NET.Sdk">
492
+ <PropertyGroup>
493
+ <TargetFrameworks>net7.0;net8.0</TargetFrameworks>
494
+ </PropertyGroup>
495
+
496
+ <ItemGroup>
497
+ <PackageReference Include="Some.Package" />
498
+ </ItemGroup>
499
+ </Project>
500
+ """),
501
+ ("Directory.Build.props", "<Project />"),
502
+ ("Directory.Packages.props", """
503
+ <Project>
504
+ <PropertyGroup>
505
+ <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
506
+ <SomePackageVersion>9.0.1</SomePackageVersion>
507
+ </PropertyGroup>
508
+
509
+ <ItemGroup>
510
+ <PackageVersion Include="Some.Package" Version="$(SomePackageVersion)" />
511
+ </ItemGroup>
512
+ </Project>
513
+ """),
514
+ (solutionPath, """
515
+ Microsoft Visual Studio Solution File, Format Version 12.00
516
+ # Visual Studio 14
517
+ VisualStudioVersion = 14.0.22705.0
518
+ MinimumVisualStudioVersion = 10.0.40219.1
519
+ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProJect", ".\src\ProJect.csproj", "{782E0C0A-10D3-444D-9640-263D03D2B20C}"
520
+ EndProject
521
+ Global
522
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
523
+ Debug|Any CPU = Debug|Any CPU
524
+ Release|Any CPU = Release|Any CPU
525
+ EndGlobalSection
526
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
527
+ {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
528
+ {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.Build.0 = Debug|Any CPU
529
+ {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.ActiveCfg = Release|Any CPU
530
+ {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.Build.0 = Release|Any CPU
531
+ EndGlobalSection
532
+ GlobalSection(SolutionProperties) = preSolution
533
+ HideSolutionNode = FALSE
534
+ EndGlobalSection
535
+ EndGlobal
536
+ """),
537
+ },
538
+ expectedResult: new()
539
+ {
540
+ Path = "",
541
+ ExpectedProjectCount = 2,
542
+ Projects = [
543
+ new()
544
+ {
545
+ FilePath = "src/project.csproj",
546
+ TargetFrameworks = ["net7.0", "net8.0"],
547
+ ExpectedDependencyCount = 2,
548
+ Dependencies = [
549
+ new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk),
550
+ new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true)
551
+ ],
552
+ Properties = [
553
+ new("ManagePackageVersionsCentrally", "true", "Directory.Packages.props"),
554
+ new("SomePackageVersion", "9.0.1", "Directory.Packages.props"),
555
+ new("TargetFrameworks", "net7.0;net8.0", "src/project.csproj"),
556
+ ]
557
+ }
558
+ ],
559
+ DirectoryPackagesProps = new()
560
+ {
561
+ FilePath = "Directory.Packages.props",
562
+ Dependencies = [
563
+ new("Some.Package", "9.0.1", DependencyType.PackageVersion, IsDirect: true)
564
+ ],
565
+ },
566
+ }
567
+ );
568
+ }
569
+
570
+ [Fact]
571
+ public async Task TestDirsProj_CasingMismatchIsResolved()
572
+ {
573
+ var dirsProjPath = "dirs.proj";
574
+ await TestDiscoveryAsync(
575
+ packages:
576
+ [
577
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"),
578
+ ],
579
+ workspacePath: "",
580
+ files: new[]
581
+ {
582
+ ("src/project.csproj", """
583
+ <Project Sdk="Microsoft.NET.Sdk">
584
+ <PropertyGroup>
585
+ <TargetFrameworks>net7.0;net8.0</TargetFrameworks>
586
+ </PropertyGroup>
587
+
588
+ <ItemGroup>
589
+ <PackageReference Include="Some.Package" />
590
+ </ItemGroup>
591
+ </Project>
592
+ """),
593
+ ("Directory.Build.props", "<Project />"),
594
+ ("Directory.Packages.props", """
595
+ <Project>
596
+ <PropertyGroup>
597
+ <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
598
+ <SomePackageVersion>9.0.1</SomePackageVersion>
599
+ </PropertyGroup>
600
+
601
+ <ItemGroup>
602
+ <PackageVersion Include="Some.Package" Version="$(SomePackageVersion)" />
603
+ </ItemGroup>
604
+ </Project>
605
+ """),
606
+ // Introduce a casing difference in the project reference
607
+ (dirsProjPath, """
608
+ <Project>
609
+ <ItemGroup>
610
+ <ProjectReference Include="SRC/PROJECT.CSPROJ" />
611
+ </ItemGroup>
612
+ </Project>
613
+ """)
614
+ },
615
+ expectedResult: new()
616
+ {
617
+ Path = "",
618
+ ExpectedProjectCount = 2,
619
+ Projects = [
620
+ new()
621
+ {
622
+ FilePath = "src/project.csproj",
623
+ TargetFrameworks = ["net7.0", "net8.0"],
624
+ ExpectedDependencyCount = 2,
625
+ Dependencies = [
626
+ new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk),
627
+ new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true)
628
+ ],
629
+ Properties = [
630
+ new("ManagePackageVersionsCentrally", "true", "Directory.Packages.props"),
631
+ new("SomePackageVersion", "9.0.1", "Directory.Packages.props"),
632
+ new("TargetFrameworks", "net7.0;net8.0", "src/project.csproj"),
633
+ ]
634
+ }
635
+ ],
636
+ DirectoryPackagesProps = new()
637
+ {
638
+ FilePath = "Directory.Packages.props",
639
+ Dependencies = [
640
+ new("Some.Package", "9.0.1", DependencyType.PackageVersion, IsDirect: true)
641
+ ],
642
+ },
643
+ }
644
+ );
645
+ }
646
+
378
647
  [Fact]
379
648
  public async Task NonSupportedProjectExtensionsAreSkipped()
380
649
  {