Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/release-notes/1.31/6632-local-archive-scan-override.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Bug Fixes

### Minor Bug Fixes

* Skip the local archive malware scan immediately when its approved override is requested, avoiding unnecessary memory use for large archive installs.
2 changes: 1 addition & 1 deletion src/AppInstallerCLICore/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(AllowRebootArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ArchitectureArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ArchiveFailedMalwareScan);
WINGET_DEFINE_RESOURCE_STRINGID(ArchiveFailedMalwareScanOverridden);
WINGET_DEFINE_RESOURCE_STRINGID(ArchiveMalwareScanSkipped);
WINGET_DEFINE_RESOURCE_STRINGID(ArgumentForSinglePackageProvidedWithMultipleQueries);
WINGET_DEFINE_RESOURCE_STRINGID(AuthenticationAccountArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(AuthenticationModeArgumentDescription);
Expand Down
43 changes: 22 additions & 21 deletions src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,30 @@ namespace AppInstaller::CLI::Workflow

void ScanArchiveFromLocalManifest(Execution::Context& context)
{
if (context.Args.Contains(Execution::Args::Type::Manifest))
if (!context.Args.Contains(Execution::Args::Type::Manifest))
{
bool scanResult = Archive::ScanZipFile(context.Get<Execution::Data::InstallerPath>());
return;
}

if (scanResult)
{
AICLI_LOG(CLI, Info, << "Archive malware scan passed");
}
else
{
if (context.Args.Contains(Execution::Args::Type::IgnoreLocalArchiveMalwareScan) &&
Settings::IsAdminSettingEnabled(Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride))
{
AICLI_LOG(CLI, Warning, << "Archive scan detected malware. Proceeding due to --ignore-local-archive-malware-scan");
context.Reporter.Warn() << Resource::String::ArchiveFailedMalwareScanOverridden << std::endl;
}
else
{
AICLI_LOG(CLI, Error, << "Archive malware scan failed");
context.Reporter.Error() << Resource::String::ArchiveFailedMalwareScan << std::endl;
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_ARCHIVE_SCAN_FAILED);
}
}
if (context.Args.Contains(Execution::Args::Type::IgnoreLocalArchiveMalwareScan) &&
Settings::IsAdminSettingEnabled(Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride))
{
AICLI_LOG(CLI, Warning, << "Skipping local archive malware scan due to --ignore-local-archive-malware-scan");
context.Reporter.Warn() << Resource::String::ArchiveMalwareScanSkipped << std::endl;
return;
}

bool scanResult = Archive::ScanZipFile(context.Get<Execution::Data::InstallerPath>());

if (scanResult)
{
AICLI_LOG(CLI, Info, << "Archive malware scan passed");
}
else
{
AICLI_LOG(CLI, Error, << "Archive malware scan failed");
context.Reporter.Error() << Resource::String::ArchiveFailedMalwareScan << std::endl;
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_ARCHIVE_SCAN_FAILED);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
Original file line number Diff line number Diff line change
Expand Up @@ -1618,8 +1618,8 @@ Please specify one of them using the --source option to proceed.</value>
<value>Archive scan detected malware. To override this check use --ignore-local-archive-malware-scan</value>
<comment>{Locked="--ignore-local-archive-malware-scan"}</comment>
</data>
<data name="ArchiveFailedMalwareScanOverridden" xml:space="preserve">
<value>Archive scan detected malware. Proceeding due to --ignore-local-archive-malware-scan</value>
<data name="ArchiveMalwareScanSkipped" xml:space="preserve">
<value>Archive malware scan skipped due to --ignore-local-archive-malware-scan</value>
<comment>{Locked="--ignore-local-archive-malware-scan"}</comment>
</data>
<data name="NoUpgradeArgumentDescription" xml:space="preserve">
Expand Down
6 changes: 4 additions & 2 deletions src/AppInstallerCLITests/InstallFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,13 +486,15 @@ TEST_CASE("InstallFlow_Zip_ArchiveScanOverride_AdminSettingEnabled", "[InstallFl
EnableAdminSetting(AppInstaller::Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride);

TestHook::SetScanArchiveResult_Override scanArchiveResultOverride(false);
TestHook::SetScanArchiveCalled_Override scanArchiveCalled;

InstallCommand install({});
install.Execute(context);
INFO(installOutput.str());

// Verify override message is displayed to the user.
REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::ArchiveFailedMalwareScanOverridden).get()) != std::string::npos);
// Verify the scan is skipped and the user is notified.
REQUIRE_FALSE(scanArchiveCalled.WasCalled());
REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::ArchiveMalwareScanSkipped).get()) != std::string::npos);

// Verify Installer is called and parameters are passed in.
REQUIRE(std::filesystem::exists(installResultPath.GetPath()));
Expand Down
22 changes: 22 additions & 0 deletions src/AppInstallerCLITests/TestHooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ namespace AppInstaller
namespace Archive
{
void TestHook_SetScanArchiveResult_Override(bool* status);
void TestHook_SetScanArchiveCalled_Override(bool* status);
}

namespace CLI::Execution
Expand Down Expand Up @@ -166,6 +167,27 @@ namespace TestHook
bool m_status;
};

struct SetScanArchiveCalled_Override
{
SetScanArchiveCalled_Override()
{
AppInstaller::Archive::TestHook_SetScanArchiveCalled_Override(&m_status);
}

~SetScanArchiveCalled_Override()
{
AppInstaller::Archive::TestHook_SetScanArchiveCalled_Override(nullptr);
}

bool WasCalled() const
{
return m_status;
}

private:
bool m_status = false;
};

// Makes every source package validate as trusted, so that the pre-indexed stores can be driven
// against packages built by the test rather than against signed test data.
struct SetSourcePackageTrustValidation_Override
Expand Down
11 changes: 11 additions & 0 deletions src/AppInstallerCommonCore/Archive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,27 @@ namespace AppInstaller::Archive

#ifndef AICLI_DISABLE_TEST_HOOKS
static bool* s_ScanArchiveResult_TestHook_Override = nullptr;
static bool* s_ScanArchiveCalled_TestHook_Override = nullptr;

void TestHook_SetScanArchiveResult_Override(bool* status)
{
s_ScanArchiveResult_TestHook_Override = status;
}

void TestHook_SetScanArchiveCalled_Override(bool* status)
{
s_ScanArchiveCalled_TestHook_Override = status;
}
#endif

bool ScanZipFile(const std::filesystem::path& zipPath)
{
#ifndef AICLI_DISABLE_TEST_HOOKS
if (s_ScanArchiveCalled_TestHook_Override)
{
*s_ScanArchiveCalled_TestHook_Override = true;
}

if (s_ScanArchiveResult_TestHook_Override)
{
return *s_ScanArchiveResult_TestHook_Override;
Expand Down
Loading