Skip to content

Commit

Permalink
(#1144) Implement usePackageHashValidation feature
Browse files Browse the repository at this point in the history
This adds a check to both install and upgrade to validate that the
downloaded .nupkg file has the same hash as the source metadata.
The check is conducted before the package is installed. If the
source does not provide a sha512 checksum or if
usePackageHashValidation is disabled, then the check is skipped.

Only sha512 is supported because it is the only provided package
hash type after download. The provided hash is used because it
accounts for package signing correctly.
  • Loading branch information
TheCakeIsNaOH committed Jan 10, 2024
1 parent d1ad9a9 commit 19d7089
Showing 1 changed file with 79 additions and 2 deletions.
81 changes: 79 additions & 2 deletions src/chocolatey/infrastructure.app/services/NugetService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace chocolatey.infrastructure.app.services
using NuGet.Resolver;
using NuGet.Versioning;
using chocolatey.infrastructure.services;
using cryptography;

//todo: #2575 - this monolith is too large. Refactor once test coverage is up.

Expand Down Expand Up @@ -811,7 +812,45 @@ Version was specified as '{0}'. It is possible that version
NuGetEnvironment.GetFolderPath(NuGetFolderPath.Temp),
_nugetLogger, CancellationToken.None).GetAwaiter().GetResult())
{
//TODO, do check on downloadResult
if (!config.Features.UsePackageHashValidation)
{
this.Log().Debug("Skipping package hash validation");
}
else if (packageDependencyInfo.PackageHash is null)
{
// Folder based sources and v3 api based sources do not provide package hashes when getting metadata
this.Log().Debug("Source does not provide a package hash, skipping package checksum validation");
}
else
{
var hashInfo = HashConverter.ConvertHashToHex(packageDependencyInfo.PackageHash);

if (hashInfo.hashType == CryptoHashProviderType.Sha512)
{
using (var metadataFileStream =
downloadResult.PackageReader.GetStream(PackagingCoreConstants.NupkgMetadataFileExtension))
{
var metadataFileContents = NupkgMetadataFileFormat.Read(metadataFileStream, _nugetLogger,
PackagingCoreConstants.NupkgMetadataFileExtension);
if (hashInfo.convertedHash.Equals(metadataFileContents.ContentHash, StringComparison.OrdinalIgnoreCase))
{
this.Log().Debug("Package checksum matches expected checksum");
}
else
{
var errorMessage =
"Package checksum '{0}' did not match expected checksum '{1}'"
.FormatWith(metadataFileContents.ContentHash,
hashInfo.convertedHash);
throw new InvalidDataException(errorMessage);
}
}
}
else
{
this.Log().Warn("Server is not providing a sha512 checksum, cannot validate package checksum.");
}
}

nugetProject.InstallPackageAsync(
packageDependencyInfo,
Expand Down Expand Up @@ -1493,7 +1532,45 @@ public virtual ConcurrentDictionary<string, PackageResult> Upgrade(ChocolateyCon
NuGetEnvironment.GetFolderPath(NuGetFolderPath.Temp),
_nugetLogger, CancellationToken.None).GetAwaiter().GetResult())
{
//TODO, do check on downloadResult
if (!config.Features.UsePackageHashValidation)
{
this.Log().Debug("Skipping package hash validation");
}
else if (packageDependencyInfo.PackageHash is null)
{
// Folder based sources and v3 api based sources do not provide package hashes when getting metadata
this.Log().Debug("Source does not provide a package hash, skipping package checksum validation");
}
else
{
var hashInfo = HashConverter.ConvertHashToHex(packageDependencyInfo.PackageHash);

if (hashInfo.hashType == CryptoHashProviderType.Sha512)
{
using (var metadataFileStream =
downloadResult.PackageReader.GetStream(PackagingCoreConstants.NupkgMetadataFileExtension))
{
var metadataFileContents = NupkgMetadataFileFormat.Read(metadataFileStream, _nugetLogger,
PackagingCoreConstants.NupkgMetadataFileExtension);
if (hashInfo.convertedHash.Equals(metadataFileContents.ContentHash, StringComparison.OrdinalIgnoreCase))
{
this.Log().Debug("Package checksum matches expected checksum");
}
else
{
var errorMessage =
"Package checksum '{0}' did not match expected checksum '{1}'"
.FormatWith(metadataFileContents.ContentHash,
hashInfo.convertedHash);
throw new InvalidDataException(errorMessage);
}
}
}
else
{
this.Log().Warn("Server is not providing a sha512 checksum, cannot validate package checksum.");
}
}

nugetProject.InstallPackageAsync(
packageDependencyInfo,
Expand Down

0 comments on commit 19d7089

Please sign in to comment.