Skip to content

Commit 23ae687

Browse files
committed
fix(security): use LOAD_LIBRARY_SEARCH_* safe flags in Windows loader
Replace LOAD_WITH_ALTERED_SEARCH_PATH (0x8) with LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | _USER_DIRS | _SYSTEM32. The old flag sets the DLL's own directory as the first search path but leaves the legacy unsafe search order (CWD, %PATH%) enabled for transitive dependencies — a real DLL-hijack vector if libwebp.dll itself depends on or is patched to depend on an attacker-droppable basename. The new flag set restricts dependency resolution to the DLL's directory plus System32 (and any user-added directories), explicitly excluding CWD and %PATH%. Fall back to LOAD_WITH_ALTERED_SEARCH_PATH on ERROR_INVALID_PARAMETER (87) for pre-KB2533623 Windows, so we don't regress loading on very old hosts. Only applies to !NETCOREAPP — .NET Core uses NativeLibrary.TryLoad and the DllImportResolver in NativeLibraryBootstrap.
1 parent aadad0c commit 23ae687

1 file changed

Lines changed: 30 additions & 2 deletions

File tree

src/Imazen.WebP/NativeLibraryLoading.cs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,10 +491,38 @@ internal static class WindowsLoadLibrary
491491
SetLastError = true)]
492492
private static extern IntPtr LoadLibraryEx(string fileName, IntPtr reservedNull, uint flags);
493493

494+
// Safe-search flags (Windows 7 SP1+KB2533623 and later — universally
495+
// available on supported Windows today). These restrict dependency
496+
// resolution to the DLL's own directory plus System32 plus the
497+
// user-added directories. They explicitly exclude the legacy unsafe
498+
// search order (current working directory, %PATH%, etc.) that
499+
// LOAD_WITH_ALTERED_SEARCH_PATH leaves enabled for transitive
500+
// dependencies.
501+
private const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100;
502+
private const uint LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400;
503+
private const uint LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800;
504+
private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
505+
494506
public static IntPtr Execute(string fileName)
495507
{
496-
const uint loadWithAlteredSearchPath = 0x00000008;
497-
return LoadLibraryEx(fileName, IntPtr.Zero, loadWithAlteredSearchPath);
508+
const uint safeSearch =
509+
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
510+
LOAD_LIBRARY_SEARCH_USER_DIRS |
511+
LOAD_LIBRARY_SEARCH_SYSTEM32;
512+
513+
IntPtr handle = LoadLibraryEx(fileName, IntPtr.Zero, safeSearch);
514+
if (handle != IntPtr.Zero) return handle;
515+
516+
// ERROR_INVALID_PARAMETER (87) on very old Windows without the
517+
// KB2533623 update — fall back to the legacy flag rather than
518+
// failing outright. Any other error (file not found, image
519+
// format, etc.) propagates the original error code.
520+
int err = Marshal.GetLastWin32Error();
521+
if (err == 87)
522+
{
523+
handle = LoadLibraryEx(fileName, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
524+
}
525+
return handle;
498526
}
499527
}
500528

0 commit comments

Comments
 (0)