Relevant area(s)
WinGet CLI, portable packages, upgrade
Relevant command(s)
winget update --id GitHub.Copilot --exact --source winget --accept-source-agreements --disable-interactivity --silent --include-unknown --accept-package-agreements --force
winget update --id Gyan.FFmpeg --exact --source winget --accept-source-agreements --disable-interactivity --silent --include-unknown --accept-package-agreements --force
Brief description of your issue
Upgrading user-scope portable zip packages fails after the archive is downloaded, hash-verified, and extracted. The failure happens while WinGet is handling the existing portable command alias in the user portable links directory.
Two different portable packages fail the same way:
An unexpected error occurred while executing the command:
weakly_canonical: The path cannot be traversed because it contains an untrusted mount point.: "%LOCALAPPDATA%\Microsoft\WinGet\Links\copilot.exe"
Installer failed with exit code: 0x8a150003 : Executing command failed
Process return value: "-1978335150" (0x8A150052)
An unexpected error occurred while executing the command:
weakly_canonical: The path cannot be traversed because it contains an untrusted mount point.: "%LOCALAPPDATA%\Microsoft\WinGet\Links\ffmpeg.exe"
Installer failed with exit code: 0x8a150003 : Executing command failed
Process return value: "-1978335150" (0x8A150052)
The existing aliases are normal user-scope symlinks created under %LOCALAPPDATA%\Microsoft\WinGet\Links, and their targets exist under %LOCALAPPDATA%\Microsoft\WinGet\Packages.
Examples:
%LOCALAPPDATA%\Microsoft\WinGet\Links\copilot.exe
-> %LOCALAPPDATA%\Microsoft\WinGet\Packages\GitHub.Copilot_Microsoft.Winget.Source_8wekyb3d8bbwe\copilot.exe
%LOCALAPPDATA%\Microsoft\WinGet\Links\ffmpeg.exe
-> %LOCALAPPDATA%\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-8.1-full_build\bin\ffmpeg.exe
A small local repro suggests this is an interaction between std::filesystem::weakly_canonical and Windows RedirectionGuard / ProcessRedirectionTrustPolicy. In a normal MSVC process, std::filesystem::weakly_canonical resolves the WinGet-created alias successfully. If the same test process first enables ProcessRedirectionTrustPolicy, it throws the same exception string WinGet logs.
Normal process:
%LOCALAPPDATA%\Microsoft\WinGet\Packages\GitHub.Copilot_Microsoft.Winget.Source_8wekyb3d8bbwe\copilot.exe
%LOCALAPPDATA%\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-8.1-full_build\bin\ffmpeg.exe
Process with ProcessRedirectionTrustPolicy enabled:
weakly_canonical: The path cannot be traversed because it contains an untrusted mount point.: "%LOCALAPPDATA%\Microsoft\WinGet\Links\copilot.exe"
weakly_canonical: The path cannot be traversed because it contains an untrusted mount point.: "%LOCALAPPDATA%\Microsoft\WinGet\Links\ffmpeg.exe"
I do not know whether WinGet is explicitly enabling that mitigation, inheriting it from the packaged process context, or being affected by a newer Windows build behavior. The observable result is that WinGet preview cannot upgrade existing user-scope portable packages whose aliases are symlinks created in the normal portable links directory.
Steps to reproduce
- Use WinGet preview v1.29.140-preview / DesktopAppInstaller v1.29.139.0.
- Have an older user-scope portable zip package installed with command aliases under
%LOCALAPPDATA%\Microsoft\WinGet\Links. Reproduced with:
GitHub.Copilot installed at v1.0.24, upgrade available to v1.0.40
Gyan.FFmpeg installed at 8.1, upgrade available to 8.1.1
- Run one of:
winget update --id GitHub.Copilot --exact --source winget --accept-source-agreements --disable-interactivity --silent --include-unknown --accept-package-agreements --force
winget update --id Gyan.FFmpeg --exact --source winget --accept-source-agreements --disable-interactivity --silent --include-unknown --accept-package-agreements --force
Expected behavior
WinGet should upgrade the portable package and update/recreate its command aliases, or report a package-specific actionable failure.
Actual behavior
WinGet downloads, verifies, and extracts the archive, then fails during portable install with:
weakly_canonical: The path cannot be traversed because it contains an untrusted mount point.
Installer failed with exit code: 0x8a150003 : Executing command failed
Process return value: "-1978335150" (0x8A150052)
Relevant log lines:
[CLI ] Successfully extracted archive
[REPO] Opening database for ReadWrite at '%LOCALAPPDATA%\Microsoft\WinGet\Packages\GitHub.Copilot_Microsoft.Winget.Source_8wekyb3d8bbwe\GitHub.Copilot_Microsoft.Winget.Source_8wekyb3d8bbwe.db'
[REPO] Opened Portable Index with version [1.0]
[CLI ] Caught std::exception: weakly_canonical: The path cannot be traversed because it contains an untrusted mount point.: "%LOCALAPPDATA%\Microsoft\WinGet\Links\copilot.exe"
[CLI ] Portable installer failed: 2316632067
[CLI ] Terminating context: 0x8a150052 at C:\__w\1\s\external\pkg\src\AppInstallerCLICore\Workflows\InstallFlow.cpp:237
The Gyan.FFmpeg failure is the same, except the alias path is %LOCALAPPDATA%\Microsoft\WinGet\Links\ffmpeg.exe.
Minimal repro for the underlying filesystem exception
This does not use WinGet internals. It demonstrates that Windows rejects weakly_canonical on the existing WinGet-created symlink when ProcessRedirectionTrustPolicy is enabled.
#include <filesystem>
#include <iostream>
#include <windows.h>
int wmain(int argc, wchar_t** argv)
{
if (argc != 2)
{
std::wcerr << L"usage: redirection_trust_probe <path>\n";
return 2;
}
PROCESS_MITIGATION_REDIRECTION_TRUST_POLICY policy{};
policy.EnforceRedirectionTrust = 1;
if (!SetProcessMitigationPolicy(ProcessRedirectionTrustPolicy, &policy, sizeof(policy)))
{
std::cerr << "SetProcessMitigationPolicy failed: " << GetLastError() << "\n";
return 3;
}
try
{
std::wcout << std::filesystem::weakly_canonical(argv[1]).wstring() << L"\n";
return 0;
}
catch (const std::exception& e)
{
std::cerr << e.what() << "\n";
return 1;
}
}
Compile:
cl /std:c++17 /EHsc redirection_trust_probe.cpp /Fe:redirection_trust_probe.exe
Run:
redirection_trust_probe.exe "%LOCALAPPDATA%\Microsoft\WinGet\Links\copilot.exe"
redirection_trust_probe.exe "%LOCALAPPDATA%\Microsoft\WinGet\Links\ffmpeg.exe"
Environment
Windows Package Manager (Preview) v1.29.140-preview
Windows: Windows.Desktop v10.0.26300.8346
System Architecture: X64
Package: Microsoft.DesktopAppInstaller v1.29.139.0
Portable Links Directory (User) %LOCALAPPDATA%\Microsoft\WinGet\Links
Portable Package Root (User) %LOCALAPPDATA%\Microsoft\WinGet\Packages
Relevant area(s)
WinGet CLI, portable packages, upgrade
Relevant command(s)
Brief description of your issue
Upgrading user-scope portable zip packages fails after the archive is downloaded, hash-verified, and extracted. The failure happens while WinGet is handling the existing portable command alias in the user portable links directory.
Two different portable packages fail the same way:
The existing aliases are normal user-scope symlinks created under
%LOCALAPPDATA%\Microsoft\WinGet\Links, and their targets exist under%LOCALAPPDATA%\Microsoft\WinGet\Packages.Examples:
A small local repro suggests this is an interaction between
std::filesystem::weakly_canonicaland Windows RedirectionGuard /ProcessRedirectionTrustPolicy. In a normal MSVC process,std::filesystem::weakly_canonicalresolves the WinGet-created alias successfully. If the same test process first enablesProcessRedirectionTrustPolicy, it throws the same exception string WinGet logs.Normal process:
Process with
ProcessRedirectionTrustPolicyenabled:I do not know whether WinGet is explicitly enabling that mitigation, inheriting it from the packaged process context, or being affected by a newer Windows build behavior. The observable result is that WinGet preview cannot upgrade existing user-scope portable packages whose aliases are symlinks created in the normal portable links directory.
Steps to reproduce
%LOCALAPPDATA%\Microsoft\WinGet\Links. Reproduced with:GitHub.Copilotinstalled atv1.0.24, upgrade available tov1.0.40Gyan.FFmpeginstalled at8.1, upgrade available to8.1.1Expected behavior
WinGet should upgrade the portable package and update/recreate its command aliases, or report a package-specific actionable failure.
Actual behavior
WinGet downloads, verifies, and extracts the archive, then fails during portable install with:
Relevant log lines:
The
Gyan.FFmpegfailure is the same, except the alias path is%LOCALAPPDATA%\Microsoft\WinGet\Links\ffmpeg.exe.Minimal repro for the underlying filesystem exception
This does not use WinGet internals. It demonstrates that Windows rejects
weakly_canonicalon the existing WinGet-created symlink whenProcessRedirectionTrustPolicyis enabled.Compile:
cl /std:c++17 /EHsc redirection_trust_probe.cpp /Fe:redirection_trust_probe.exeRun:
Environment