Skip to content

Avoid rooting cryptography through ZipArchive on browser - #130688

Merged
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support
Aug 11, 2026
Merged

Avoid rooting cryptography through ZipArchive on browser#130688
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support

Conversation

CopilotAI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Fixes#130650
which is regression from #122093

Using ZipArchive on browser-wasm unnecessarily retained System.Security.Cryptography, increasing trimmed application size even though WinZip AES is unsupported there.

Changes

  • Exclude WinZip AES implementation files and the cryptography project reference from browser builds.
  • Provide browser-specific WinZip AES stubs that continue throwing PlatformNotSupportedException.
  • Keep ZipCrypto supported by removing its cryptography dependency:
    • Generate header randomness with Guid.NewGuid().
    • Clear pooled password buffers with Array.Clear.
  • Add coverage ensuring browser ZipCrypto remains functional and the wasm dependency closure excludes System.Security.Cryptography.

CopilotAIand others added 2 commits July 14, 2026 13:30
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI self-assigned this Jul 14, 2026
CopilotAI review requested due to automatic review settings July 14, 2026 14:01
CopilotAI removed the request for review from CopilotJuly 14, 2026 14:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:34
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:48
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1072

  • This browser-only test validates ZipCrypto decryption, but this PR also changes browser behavior by swapping in WinZip AES stubs. Consider also asserting that opening the AES-encrypted entry in the same archive throws PlatformNotSupportedException, so the new stub path is exercised on Browser and regressions are caught.
 ZipArchiveEntry entry = archive.GetEntry("hello.txt");
Assert.NotNull(entry);
Assert.Equal(ZipEncryptionMethod.ZipCrypto, entry.EncryptionMethod);
using Stream entryStream = await OpenEntryStream(async, entry, Password);
using StreamReader reader = new(entryStream);

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs:30

  • GetCryptographicallySecureRandomBytes currently forwards to GetRandomBytes, which throws InvalidOperationException on most failures. Since the method name (and the Unix implementation) implies cryptographic RNG semantics, it should throw CryptographicException for non-OOM failures to better match RandomNumberGenerator behavior.
 // BCryptGenRandom with BCRYPT_USE_SYSTEM_PREFERRED_RNG is always cryptographically secure.
internal static unsafe void GetCryptographicallySecureRandomBytes(byte* buffer, int length) =>
GetRandomBytes(buffer, length);

alinpahontu2912and others added 2 commits August 6, 2026 16:50
- Rename the sole BCrypt-backed method in
Interop.BCryptGenRandom.GetRandomBytes.cs to
GetCryptographicallySecureRandomBytes directly, removing the
pass-through alias wrapper (file name kept unchanged).
- Add a short comment at the ZipCryptoStream.Random.cs call site noting
the call is cryptographically secure on all platforms.
- Extend DecryptZipCryptoEntry_Browser to also assert that creating a
WinZip AES-encrypted entry on browser throws PlatformNotSupportedException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c
Keep the original GetRandomBytes name in the BCrypt interop file and
restore GetCryptographicallySecureRandomBytes as a thin wrapper, with a
comment explaining why the wrapper exists: it gives the Windows method
the same name as the Unix crypto-secure API, so shared cross-platform
callers (ZipCryptoStream) reliably get a cryptographically secure
implementation on every platform.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:785

  • keySizeBits is computed but never used in this AES update-mode path. This is dead code and can produce warnings / confusion; it should be removed (the key size was already baked into _derivedAesKeyMaterial).
 // Determine the actual compression method to use
// The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

…rator elsewhere
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:9

  • The WinZipAesKeyMaterial stub is declared as internal readonly struct WinZipAesKeyMaterial; which is not valid C# syntax (types can’t be forward-declared with a trailing semicolon). This will fail to compile on browser builds.
 internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System.IO.Compression.csproj:128

  • System.Security.Cryptography doesn’t target $(NetCoreAppCurrent)-wasi (its csproj only includes windows/unix/android/apple/browser/$(NetCoreAppCurrent)), so keeping this ProjectReference for wasi will break the wasi build. The condition should exclude wasi as well as browser.
 <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Cryptography\src\System.Security.Cryptography.csproj" Condition="'$(TargetPlatformIdentifier)' != 'browser'" />

Comment threadsrc/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:10

  • WinZipAesKeyMaterial is declared with a trailing semicolon, which isn’t valid C# (C# doesn’t support forward-declaring structs). Browser builds will fail to compile this file.
{
internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:786

  • In this AES update-mode branch, int keySizeBits = GetAesKeySizeBits(Encryption); (a few lines above) is assigned but never used. If warnings are treated as errors, this will break the build; if the call is only for validation, discard the value explicitly.
 // The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(
baseStream: _archive.ArchiveStream,

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1078

  • This browser-only test validates ZipCrypto decryption, but it doesn’t cover creating a ZipCrypto entry on browser. Since this PR changes the ZipCrypto encryption path (header salt generation + password buffer clearing), adding a round-trip create/read assertion here would help prevent regressions.
 using MemoryStream createStream = new();
ZipArchive createArchive = await CreateZipArchive(async, createStream, ZipArchiveMode.Create, leaveOpen: true);
Assert.Throws<PlatformNotSupportedException>(() => createArchive.CreateEntry("aes.txt", Password, ZipEncryptionMethod.Aes256));
await DisposeZipArchive(async, createArchive);
}

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs:626

  • ReadEncryptionSaltIfNeeded now returns early on browser/wasi without populating _aesSalt. In the sync open path (WrapWithDecryptionIfNeeded), AES entries first check _aesSalt is null and throw InvalidDataException(SR.LocalFileHeaderCorrupt), so on browser/wasi this can surface as “corrupt header” instead of the intended PlatformNotSupportedException for WinZip AES. Consider setting a non-null sentinel salt on browser/wasi so the open path reaches the WinZipAesStream stubs and throws PNSE consistently.
 if (!IsAesEncrypted || !_originallyInArchive || OperatingSystem.IsBrowser() || OperatingSystem.IsWasi())
{
return;
}

@alinpahontu2912

Copy link
Copy Markdown
Member

/ba-g failure unrelated to my change

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasmWebAssembly architecturearea-System.IO.Compressionos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm] System.IO.Compression roots System.Security.Cryptography into every trimmed app using ZipArchive (size regression from #122093)

6 participants

@alinpahontu2912@pavelsavara@rzikm@iremyux
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Avoid rooting cryptography through ZipArchive on browser by Copilot · Pull Request #130688 · dotnet/runtime · GitHub
Skip to content

Avoid rooting cryptography through ZipArchive on browser - #130688

Merged
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support
Aug 11, 2026
Merged

Avoid rooting cryptography through ZipArchive on browser#130688
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support

Conversation

CopilotAI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Fixes#130650
which is regression from #122093

Using ZipArchive on browser-wasm unnecessarily retained System.Security.Cryptography, increasing trimmed application size even though WinZip AES is unsupported there.

Changes

  • Exclude WinZip AES implementation files and the cryptography project reference from browser builds.
  • Provide browser-specific WinZip AES stubs that continue throwing PlatformNotSupportedException.
  • Keep ZipCrypto supported by removing its cryptography dependency:
    • Generate header randomness with Guid.NewGuid().
    • Clear pooled password buffers with Array.Clear.
  • Add coverage ensuring browser ZipCrypto remains functional and the wasm dependency closure excludes System.Security.Cryptography.

CopilotAIand others added 2 commits July 14, 2026 13:30
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI self-assigned this Jul 14, 2026
CopilotAI review requested due to automatic review settings July 14, 2026 14:01
CopilotAI removed the request for review from CopilotJuly 14, 2026 14:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:34
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:48
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1072

  • This browser-only test validates ZipCrypto decryption, but this PR also changes browser behavior by swapping in WinZip AES stubs. Consider also asserting that opening the AES-encrypted entry in the same archive throws PlatformNotSupportedException, so the new stub path is exercised on Browser and regressions are caught.
 ZipArchiveEntry entry = archive.GetEntry("hello.txt");
Assert.NotNull(entry);
Assert.Equal(ZipEncryptionMethod.ZipCrypto, entry.EncryptionMethod);
using Stream entryStream = await OpenEntryStream(async, entry, Password);
using StreamReader reader = new(entryStream);

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs:30

  • GetCryptographicallySecureRandomBytes currently forwards to GetRandomBytes, which throws InvalidOperationException on most failures. Since the method name (and the Unix implementation) implies cryptographic RNG semantics, it should throw CryptographicException for non-OOM failures to better match RandomNumberGenerator behavior.
 // BCryptGenRandom with BCRYPT_USE_SYSTEM_PREFERRED_RNG is always cryptographically secure.
internal static unsafe void GetCryptographicallySecureRandomBytes(byte* buffer, int length) =>
GetRandomBytes(buffer, length);

alinpahontu2912and others added 2 commits August 6, 2026 16:50
- Rename the sole BCrypt-backed method in
Interop.BCryptGenRandom.GetRandomBytes.cs to
GetCryptographicallySecureRandomBytes directly, removing the
pass-through alias wrapper (file name kept unchanged).
- Add a short comment at the ZipCryptoStream.Random.cs call site noting
the call is cryptographically secure on all platforms.
- Extend DecryptZipCryptoEntry_Browser to also assert that creating a
WinZip AES-encrypted entry on browser throws PlatformNotSupportedException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c
Keep the original GetRandomBytes name in the BCrypt interop file and
restore GetCryptographicallySecureRandomBytes as a thin wrapper, with a
comment explaining why the wrapper exists: it gives the Windows method
the same name as the Unix crypto-secure API, so shared cross-platform
callers (ZipCryptoStream) reliably get a cryptographically secure
implementation on every platform.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:785

  • keySizeBits is computed but never used in this AES update-mode path. This is dead code and can produce warnings / confusion; it should be removed (the key size was already baked into _derivedAesKeyMaterial).
 // Determine the actual compression method to use
// The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

…rator elsewhere
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:9

  • The WinZipAesKeyMaterial stub is declared as internal readonly struct WinZipAesKeyMaterial; which is not valid C# syntax (types can’t be forward-declared with a trailing semicolon). This will fail to compile on browser builds.
 internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System.IO.Compression.csproj:128

  • System.Security.Cryptography doesn’t target $(NetCoreAppCurrent)-wasi (its csproj only includes windows/unix/android/apple/browser/$(NetCoreAppCurrent)), so keeping this ProjectReference for wasi will break the wasi build. The condition should exclude wasi as well as browser.
 <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Cryptography\src\System.Security.Cryptography.csproj" Condition="'$(TargetPlatformIdentifier)' != 'browser'" />

Comment threadsrc/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:10

  • WinZipAesKeyMaterial is declared with a trailing semicolon, which isn’t valid C# (C# doesn’t support forward-declaring structs). Browser builds will fail to compile this file.
{
internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:786

  • In this AES update-mode branch, int keySizeBits = GetAesKeySizeBits(Encryption); (a few lines above) is assigned but never used. If warnings are treated as errors, this will break the build; if the call is only for validation, discard the value explicitly.
 // The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(
baseStream: _archive.ArchiveStream,

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1078

  • This browser-only test validates ZipCrypto decryption, but it doesn’t cover creating a ZipCrypto entry on browser. Since this PR changes the ZipCrypto encryption path (header salt generation + password buffer clearing), adding a round-trip create/read assertion here would help prevent regressions.
 using MemoryStream createStream = new();
ZipArchive createArchive = await CreateZipArchive(async, createStream, ZipArchiveMode.Create, leaveOpen: true);
Assert.Throws<PlatformNotSupportedException>(() => createArchive.CreateEntry("aes.txt", Password, ZipEncryptionMethod.Aes256));
await DisposeZipArchive(async, createArchive);
}

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs:626

  • ReadEncryptionSaltIfNeeded now returns early on browser/wasi without populating _aesSalt. In the sync open path (WrapWithDecryptionIfNeeded), AES entries first check _aesSalt is null and throw InvalidDataException(SR.LocalFileHeaderCorrupt), so on browser/wasi this can surface as “corrupt header” instead of the intended PlatformNotSupportedException for WinZip AES. Consider setting a non-null sentinel salt on browser/wasi so the open path reaches the WinZipAesStream stubs and throws PNSE consistently.
 if (!IsAesEncrypted || !_originallyInArchive || OperatingSystem.IsBrowser() || OperatingSystem.IsWasi())
{
return;
}

@alinpahontu2912

Copy link
Copy Markdown
Member

/ba-g failure unrelated to my change

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasmWebAssembly architecturearea-System.IO.Compressionos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm] System.IO.Compression roots System.Security.Cryptography into every trimmed app using ZipArchive (size regression from #122093)

6 participants

@alinpahontu2912@pavelsavara@rzikm@iremyux
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Avoid rooting cryptography through ZipArchive on browser by Copilot · Pull Request #130688 · dotnet/runtime · GitHub
Skip to content

Avoid rooting cryptography through ZipArchive on browser - #130688

Merged
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support
Aug 11, 2026
Merged

Avoid rooting cryptography through ZipArchive on browser#130688
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support

Conversation

CopilotAI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Fixes#130650
which is regression from #122093

Using ZipArchive on browser-wasm unnecessarily retained System.Security.Cryptography, increasing trimmed application size even though WinZip AES is unsupported there.

Changes

  • Exclude WinZip AES implementation files and the cryptography project reference from browser builds.
  • Provide browser-specific WinZip AES stubs that continue throwing PlatformNotSupportedException.
  • Keep ZipCrypto supported by removing its cryptography dependency:
    • Generate header randomness with Guid.NewGuid().
    • Clear pooled password buffers with Array.Clear.
  • Add coverage ensuring browser ZipCrypto remains functional and the wasm dependency closure excludes System.Security.Cryptography.

CopilotAIand others added 2 commits July 14, 2026 13:30
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI self-assigned this Jul 14, 2026
CopilotAI review requested due to automatic review settings July 14, 2026 14:01
CopilotAI removed the request for review from CopilotJuly 14, 2026 14:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:34
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:48
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1072

  • This browser-only test validates ZipCrypto decryption, but this PR also changes browser behavior by swapping in WinZip AES stubs. Consider also asserting that opening the AES-encrypted entry in the same archive throws PlatformNotSupportedException, so the new stub path is exercised on Browser and regressions are caught.
 ZipArchiveEntry entry = archive.GetEntry("hello.txt");
Assert.NotNull(entry);
Assert.Equal(ZipEncryptionMethod.ZipCrypto, entry.EncryptionMethod);
using Stream entryStream = await OpenEntryStream(async, entry, Password);
using StreamReader reader = new(entryStream);

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs:30

  • GetCryptographicallySecureRandomBytes currently forwards to GetRandomBytes, which throws InvalidOperationException on most failures. Since the method name (and the Unix implementation) implies cryptographic RNG semantics, it should throw CryptographicException for non-OOM failures to better match RandomNumberGenerator behavior.
 // BCryptGenRandom with BCRYPT_USE_SYSTEM_PREFERRED_RNG is always cryptographically secure.
internal static unsafe void GetCryptographicallySecureRandomBytes(byte* buffer, int length) =>
GetRandomBytes(buffer, length);

alinpahontu2912and others added 2 commits August 6, 2026 16:50
- Rename the sole BCrypt-backed method in
Interop.BCryptGenRandom.GetRandomBytes.cs to
GetCryptographicallySecureRandomBytes directly, removing the
pass-through alias wrapper (file name kept unchanged).
- Add a short comment at the ZipCryptoStream.Random.cs call site noting
the call is cryptographically secure on all platforms.
- Extend DecryptZipCryptoEntry_Browser to also assert that creating a
WinZip AES-encrypted entry on browser throws PlatformNotSupportedException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c
Keep the original GetRandomBytes name in the BCrypt interop file and
restore GetCryptographicallySecureRandomBytes as a thin wrapper, with a
comment explaining why the wrapper exists: it gives the Windows method
the same name as the Unix crypto-secure API, so shared cross-platform
callers (ZipCryptoStream) reliably get a cryptographically secure
implementation on every platform.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:785

  • keySizeBits is computed but never used in this AES update-mode path. This is dead code and can produce warnings / confusion; it should be removed (the key size was already baked into _derivedAesKeyMaterial).
 // Determine the actual compression method to use
// The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

…rator elsewhere
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:9

  • The WinZipAesKeyMaterial stub is declared as internal readonly struct WinZipAesKeyMaterial; which is not valid C# syntax (types can’t be forward-declared with a trailing semicolon). This will fail to compile on browser builds.
 internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System.IO.Compression.csproj:128

  • System.Security.Cryptography doesn’t target $(NetCoreAppCurrent)-wasi (its csproj only includes windows/unix/android/apple/browser/$(NetCoreAppCurrent)), so keeping this ProjectReference for wasi will break the wasi build. The condition should exclude wasi as well as browser.
 <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Cryptography\src\System.Security.Cryptography.csproj" Condition="'$(TargetPlatformIdentifier)' != 'browser'" />

Comment threadsrc/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:10

  • WinZipAesKeyMaterial is declared with a trailing semicolon, which isn’t valid C# (C# doesn’t support forward-declaring structs). Browser builds will fail to compile this file.
{
internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:786

  • In this AES update-mode branch, int keySizeBits = GetAesKeySizeBits(Encryption); (a few lines above) is assigned but never used. If warnings are treated as errors, this will break the build; if the call is only for validation, discard the value explicitly.
 // The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(
baseStream: _archive.ArchiveStream,

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1078

  • This browser-only test validates ZipCrypto decryption, but it doesn’t cover creating a ZipCrypto entry on browser. Since this PR changes the ZipCrypto encryption path (header salt generation + password buffer clearing), adding a round-trip create/read assertion here would help prevent regressions.
 using MemoryStream createStream = new();
ZipArchive createArchive = await CreateZipArchive(async, createStream, ZipArchiveMode.Create, leaveOpen: true);
Assert.Throws<PlatformNotSupportedException>(() => createArchive.CreateEntry("aes.txt", Password, ZipEncryptionMethod.Aes256));
await DisposeZipArchive(async, createArchive);
}

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs:626

  • ReadEncryptionSaltIfNeeded now returns early on browser/wasi without populating _aesSalt. In the sync open path (WrapWithDecryptionIfNeeded), AES entries first check _aesSalt is null and throw InvalidDataException(SR.LocalFileHeaderCorrupt), so on browser/wasi this can surface as “corrupt header” instead of the intended PlatformNotSupportedException for WinZip AES. Consider setting a non-null sentinel salt on browser/wasi so the open path reaches the WinZipAesStream stubs and throws PNSE consistently.
 if (!IsAesEncrypted || !_originallyInArchive || OperatingSystem.IsBrowser() || OperatingSystem.IsWasi())
{
return;
}

@alinpahontu2912

Copy link
Copy Markdown
Member

/ba-g failure unrelated to my change

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasmWebAssembly architecturearea-System.IO.Compressionos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm] System.IO.Compression roots System.Security.Cryptography into every trimmed app using ZipArchive (size regression from #122093)

6 participants

@alinpahontu2912@pavelsavara@rzikm@iremyux
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Avoid rooting cryptography through ZipArchive on browser by Copilot · Pull Request #130688 · dotnet/runtime · GitHub
Skip to content

Avoid rooting cryptography through ZipArchive on browser - #130688

Merged
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support
Aug 11, 2026
Merged

Avoid rooting cryptography through ZipArchive on browser#130688
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support

Conversation

CopilotAI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Fixes#130650
which is regression from #122093

Using ZipArchive on browser-wasm unnecessarily retained System.Security.Cryptography, increasing trimmed application size even though WinZip AES is unsupported there.

Changes

  • Exclude WinZip AES implementation files and the cryptography project reference from browser builds.
  • Provide browser-specific WinZip AES stubs that continue throwing PlatformNotSupportedException.
  • Keep ZipCrypto supported by removing its cryptography dependency:
    • Generate header randomness with Guid.NewGuid().
    • Clear pooled password buffers with Array.Clear.
  • Add coverage ensuring browser ZipCrypto remains functional and the wasm dependency closure excludes System.Security.Cryptography.

CopilotAIand others added 2 commits July 14, 2026 13:30
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI self-assigned this Jul 14, 2026
CopilotAI review requested due to automatic review settings July 14, 2026 14:01
CopilotAI removed the request for review from CopilotJuly 14, 2026 14:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:34
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:48
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1072

  • This browser-only test validates ZipCrypto decryption, but this PR also changes browser behavior by swapping in WinZip AES stubs. Consider also asserting that opening the AES-encrypted entry in the same archive throws PlatformNotSupportedException, so the new stub path is exercised on Browser and regressions are caught.
 ZipArchiveEntry entry = archive.GetEntry("hello.txt");
Assert.NotNull(entry);
Assert.Equal(ZipEncryptionMethod.ZipCrypto, entry.EncryptionMethod);
using Stream entryStream = await OpenEntryStream(async, entry, Password);
using StreamReader reader = new(entryStream);

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs:30

  • GetCryptographicallySecureRandomBytes currently forwards to GetRandomBytes, which throws InvalidOperationException on most failures. Since the method name (and the Unix implementation) implies cryptographic RNG semantics, it should throw CryptographicException for non-OOM failures to better match RandomNumberGenerator behavior.
 // BCryptGenRandom with BCRYPT_USE_SYSTEM_PREFERRED_RNG is always cryptographically secure.
internal static unsafe void GetCryptographicallySecureRandomBytes(byte* buffer, int length) =>
GetRandomBytes(buffer, length);

alinpahontu2912and others added 2 commits August 6, 2026 16:50
- Rename the sole BCrypt-backed method in
Interop.BCryptGenRandom.GetRandomBytes.cs to
GetCryptographicallySecureRandomBytes directly, removing the
pass-through alias wrapper (file name kept unchanged).
- Add a short comment at the ZipCryptoStream.Random.cs call site noting
the call is cryptographically secure on all platforms.
- Extend DecryptZipCryptoEntry_Browser to also assert that creating a
WinZip AES-encrypted entry on browser throws PlatformNotSupportedException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c
Keep the original GetRandomBytes name in the BCrypt interop file and
restore GetCryptographicallySecureRandomBytes as a thin wrapper, with a
comment explaining why the wrapper exists: it gives the Windows method
the same name as the Unix crypto-secure API, so shared cross-platform
callers (ZipCryptoStream) reliably get a cryptographically secure
implementation on every platform.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:785

  • keySizeBits is computed but never used in this AES update-mode path. This is dead code and can produce warnings / confusion; it should be removed (the key size was already baked into _derivedAesKeyMaterial).
 // Determine the actual compression method to use
// The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

…rator elsewhere
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:9

  • The WinZipAesKeyMaterial stub is declared as internal readonly struct WinZipAesKeyMaterial; which is not valid C# syntax (types can’t be forward-declared with a trailing semicolon). This will fail to compile on browser builds.
 internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System.IO.Compression.csproj:128

  • System.Security.Cryptography doesn’t target $(NetCoreAppCurrent)-wasi (its csproj only includes windows/unix/android/apple/browser/$(NetCoreAppCurrent)), so keeping this ProjectReference for wasi will break the wasi build. The condition should exclude wasi as well as browser.
 <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Cryptography\src\System.Security.Cryptography.csproj" Condition="'$(TargetPlatformIdentifier)' != 'browser'" />

Comment threadsrc/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:10

  • WinZipAesKeyMaterial is declared with a trailing semicolon, which isn’t valid C# (C# doesn’t support forward-declaring structs). Browser builds will fail to compile this file.
{
internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:786

  • In this AES update-mode branch, int keySizeBits = GetAesKeySizeBits(Encryption); (a few lines above) is assigned but never used. If warnings are treated as errors, this will break the build; if the call is only for validation, discard the value explicitly.
 // The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(
baseStream: _archive.ArchiveStream,

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1078

  • This browser-only test validates ZipCrypto decryption, but it doesn’t cover creating a ZipCrypto entry on browser. Since this PR changes the ZipCrypto encryption path (header salt generation + password buffer clearing), adding a round-trip create/read assertion here would help prevent regressions.
 using MemoryStream createStream = new();
ZipArchive createArchive = await CreateZipArchive(async, createStream, ZipArchiveMode.Create, leaveOpen: true);
Assert.Throws<PlatformNotSupportedException>(() => createArchive.CreateEntry("aes.txt", Password, ZipEncryptionMethod.Aes256));
await DisposeZipArchive(async, createArchive);
}

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs:626

  • ReadEncryptionSaltIfNeeded now returns early on browser/wasi without populating _aesSalt. In the sync open path (WrapWithDecryptionIfNeeded), AES entries first check _aesSalt is null and throw InvalidDataException(SR.LocalFileHeaderCorrupt), so on browser/wasi this can surface as “corrupt header” instead of the intended PlatformNotSupportedException for WinZip AES. Consider setting a non-null sentinel salt on browser/wasi so the open path reaches the WinZipAesStream stubs and throws PNSE consistently.
 if (!IsAesEncrypted || !_originallyInArchive || OperatingSystem.IsBrowser() || OperatingSystem.IsWasi())
{
return;
}

@alinpahontu2912

Copy link
Copy Markdown
Member

/ba-g failure unrelated to my change

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasmWebAssembly architecturearea-System.IO.Compressionos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm] System.IO.Compression roots System.Security.Cryptography into every trimmed app using ZipArchive (size regression from #122093)

6 participants

@alinpahontu2912@pavelsavara@rzikm@iremyux
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Avoid rooting cryptography through ZipArchive on browser by Copilot · Pull Request #130688 · dotnet/runtime · GitHub
Skip to content

Avoid rooting cryptography through ZipArchive on browser - #130688

Merged
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support
Aug 11, 2026
Merged

Avoid rooting cryptography through ZipArchive on browser#130688
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support

Conversation

CopilotAI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Fixes#130650
which is regression from #122093

Using ZipArchive on browser-wasm unnecessarily retained System.Security.Cryptography, increasing trimmed application size even though WinZip AES is unsupported there.

Changes

  • Exclude WinZip AES implementation files and the cryptography project reference from browser builds.
  • Provide browser-specific WinZip AES stubs that continue throwing PlatformNotSupportedException.
  • Keep ZipCrypto supported by removing its cryptography dependency:
    • Generate header randomness with Guid.NewGuid().
    • Clear pooled password buffers with Array.Clear.
  • Add coverage ensuring browser ZipCrypto remains functional and the wasm dependency closure excludes System.Security.Cryptography.

CopilotAIand others added 2 commits July 14, 2026 13:30
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI self-assigned this Jul 14, 2026
CopilotAI review requested due to automatic review settings July 14, 2026 14:01
CopilotAI removed the request for review from CopilotJuly 14, 2026 14:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:34
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:48
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1072

  • This browser-only test validates ZipCrypto decryption, but this PR also changes browser behavior by swapping in WinZip AES stubs. Consider also asserting that opening the AES-encrypted entry in the same archive throws PlatformNotSupportedException, so the new stub path is exercised on Browser and regressions are caught.
 ZipArchiveEntry entry = archive.GetEntry("hello.txt");
Assert.NotNull(entry);
Assert.Equal(ZipEncryptionMethod.ZipCrypto, entry.EncryptionMethod);
using Stream entryStream = await OpenEntryStream(async, entry, Password);
using StreamReader reader = new(entryStream);

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs:30

  • GetCryptographicallySecureRandomBytes currently forwards to GetRandomBytes, which throws InvalidOperationException on most failures. Since the method name (and the Unix implementation) implies cryptographic RNG semantics, it should throw CryptographicException for non-OOM failures to better match RandomNumberGenerator behavior.
 // BCryptGenRandom with BCRYPT_USE_SYSTEM_PREFERRED_RNG is always cryptographically secure.
internal static unsafe void GetCryptographicallySecureRandomBytes(byte* buffer, int length) =>
GetRandomBytes(buffer, length);

alinpahontu2912and others added 2 commits August 6, 2026 16:50
- Rename the sole BCrypt-backed method in
Interop.BCryptGenRandom.GetRandomBytes.cs to
GetCryptographicallySecureRandomBytes directly, removing the
pass-through alias wrapper (file name kept unchanged).
- Add a short comment at the ZipCryptoStream.Random.cs call site noting
the call is cryptographically secure on all platforms.
- Extend DecryptZipCryptoEntry_Browser to also assert that creating a
WinZip AES-encrypted entry on browser throws PlatformNotSupportedException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c
Keep the original GetRandomBytes name in the BCrypt interop file and
restore GetCryptographicallySecureRandomBytes as a thin wrapper, with a
comment explaining why the wrapper exists: it gives the Windows method
the same name as the Unix crypto-secure API, so shared cross-platform
callers (ZipCryptoStream) reliably get a cryptographically secure
implementation on every platform.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:785

  • keySizeBits is computed but never used in this AES update-mode path. This is dead code and can produce warnings / confusion; it should be removed (the key size was already baked into _derivedAesKeyMaterial).
 // Determine the actual compression method to use
// The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

…rator elsewhere
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:9

  • The WinZipAesKeyMaterial stub is declared as internal readonly struct WinZipAesKeyMaterial; which is not valid C# syntax (types can’t be forward-declared with a trailing semicolon). This will fail to compile on browser builds.
 internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System.IO.Compression.csproj:128

  • System.Security.Cryptography doesn’t target $(NetCoreAppCurrent)-wasi (its csproj only includes windows/unix/android/apple/browser/$(NetCoreAppCurrent)), so keeping this ProjectReference for wasi will break the wasi build. The condition should exclude wasi as well as browser.
 <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Cryptography\src\System.Security.Cryptography.csproj" Condition="'$(TargetPlatformIdentifier)' != 'browser'" />

Comment threadsrc/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:10

  • WinZipAesKeyMaterial is declared with a trailing semicolon, which isn’t valid C# (C# doesn’t support forward-declaring structs). Browser builds will fail to compile this file.
{
internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:786

  • In this AES update-mode branch, int keySizeBits = GetAesKeySizeBits(Encryption); (a few lines above) is assigned but never used. If warnings are treated as errors, this will break the build; if the call is only for validation, discard the value explicitly.
 // The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(
baseStream: _archive.ArchiveStream,

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1078

  • This browser-only test validates ZipCrypto decryption, but it doesn’t cover creating a ZipCrypto entry on browser. Since this PR changes the ZipCrypto encryption path (header salt generation + password buffer clearing), adding a round-trip create/read assertion here would help prevent regressions.
 using MemoryStream createStream = new();
ZipArchive createArchive = await CreateZipArchive(async, createStream, ZipArchiveMode.Create, leaveOpen: true);
Assert.Throws<PlatformNotSupportedException>(() => createArchive.CreateEntry("aes.txt", Password, ZipEncryptionMethod.Aes256));
await DisposeZipArchive(async, createArchive);
}

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs:626

  • ReadEncryptionSaltIfNeeded now returns early on browser/wasi without populating _aesSalt. In the sync open path (WrapWithDecryptionIfNeeded), AES entries first check _aesSalt is null and throw InvalidDataException(SR.LocalFileHeaderCorrupt), so on browser/wasi this can surface as “corrupt header” instead of the intended PlatformNotSupportedException for WinZip AES. Consider setting a non-null sentinel salt on browser/wasi so the open path reaches the WinZipAesStream stubs and throws PNSE consistently.
 if (!IsAesEncrypted || !_originallyInArchive || OperatingSystem.IsBrowser() || OperatingSystem.IsWasi())
{
return;
}

@alinpahontu2912

Copy link
Copy Markdown
Member

/ba-g failure unrelated to my change

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasmWebAssembly architecturearea-System.IO.Compressionos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm] System.IO.Compression roots System.Security.Cryptography into every trimmed app using ZipArchive (size regression from #122093)

6 participants

@alinpahontu2912@pavelsavara@rzikm@iremyux
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Avoid rooting cryptography through ZipArchive on browser by Copilot · Pull Request #130688 · dotnet/runtime · GitHub
Skip to content

Avoid rooting cryptography through ZipArchive on browser - #130688

Merged
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support
Aug 11, 2026
Merged

Avoid rooting cryptography through ZipArchive on browser#130688
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support

Conversation

CopilotAI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Fixes#130650
which is regression from #122093

Using ZipArchive on browser-wasm unnecessarily retained System.Security.Cryptography, increasing trimmed application size even though WinZip AES is unsupported there.

Changes

  • Exclude WinZip AES implementation files and the cryptography project reference from browser builds.
  • Provide browser-specific WinZip AES stubs that continue throwing PlatformNotSupportedException.
  • Keep ZipCrypto supported by removing its cryptography dependency:
    • Generate header randomness with Guid.NewGuid().
    • Clear pooled password buffers with Array.Clear.
  • Add coverage ensuring browser ZipCrypto remains functional and the wasm dependency closure excludes System.Security.Cryptography.

CopilotAIand others added 2 commits July 14, 2026 13:30
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI self-assigned this Jul 14, 2026
CopilotAI review requested due to automatic review settings July 14, 2026 14:01
CopilotAI removed the request for review from CopilotJuly 14, 2026 14:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:34
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:48
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1072

  • This browser-only test validates ZipCrypto decryption, but this PR also changes browser behavior by swapping in WinZip AES stubs. Consider also asserting that opening the AES-encrypted entry in the same archive throws PlatformNotSupportedException, so the new stub path is exercised on Browser and regressions are caught.
 ZipArchiveEntry entry = archive.GetEntry("hello.txt");
Assert.NotNull(entry);
Assert.Equal(ZipEncryptionMethod.ZipCrypto, entry.EncryptionMethod);
using Stream entryStream = await OpenEntryStream(async, entry, Password);
using StreamReader reader = new(entryStream);

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs:30

  • GetCryptographicallySecureRandomBytes currently forwards to GetRandomBytes, which throws InvalidOperationException on most failures. Since the method name (and the Unix implementation) implies cryptographic RNG semantics, it should throw CryptographicException for non-OOM failures to better match RandomNumberGenerator behavior.
 // BCryptGenRandom with BCRYPT_USE_SYSTEM_PREFERRED_RNG is always cryptographically secure.
internal static unsafe void GetCryptographicallySecureRandomBytes(byte* buffer, int length) =>
GetRandomBytes(buffer, length);

alinpahontu2912and others added 2 commits August 6, 2026 16:50
- Rename the sole BCrypt-backed method in
Interop.BCryptGenRandom.GetRandomBytes.cs to
GetCryptographicallySecureRandomBytes directly, removing the
pass-through alias wrapper (file name kept unchanged).
- Add a short comment at the ZipCryptoStream.Random.cs call site noting
the call is cryptographically secure on all platforms.
- Extend DecryptZipCryptoEntry_Browser to also assert that creating a
WinZip AES-encrypted entry on browser throws PlatformNotSupportedException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c
Keep the original GetRandomBytes name in the BCrypt interop file and
restore GetCryptographicallySecureRandomBytes as a thin wrapper, with a
comment explaining why the wrapper exists: it gives the Windows method
the same name as the Unix crypto-secure API, so shared cross-platform
callers (ZipCryptoStream) reliably get a cryptographically secure
implementation on every platform.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:785

  • keySizeBits is computed but never used in this AES update-mode path. This is dead code and can produce warnings / confusion; it should be removed (the key size was already baked into _derivedAesKeyMaterial).
 // Determine the actual compression method to use
// The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

…rator elsewhere
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:9

  • The WinZipAesKeyMaterial stub is declared as internal readonly struct WinZipAesKeyMaterial; which is not valid C# syntax (types can’t be forward-declared with a trailing semicolon). This will fail to compile on browser builds.
 internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System.IO.Compression.csproj:128

  • System.Security.Cryptography doesn’t target $(NetCoreAppCurrent)-wasi (its csproj only includes windows/unix/android/apple/browser/$(NetCoreAppCurrent)), so keeping this ProjectReference for wasi will break the wasi build. The condition should exclude wasi as well as browser.
 <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Cryptography\src\System.Security.Cryptography.csproj" Condition="'$(TargetPlatformIdentifier)' != 'browser'" />

Comment threadsrc/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:10

  • WinZipAesKeyMaterial is declared with a trailing semicolon, which isn’t valid C# (C# doesn’t support forward-declaring structs). Browser builds will fail to compile this file.
{
internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:786

  • In this AES update-mode branch, int keySizeBits = GetAesKeySizeBits(Encryption); (a few lines above) is assigned but never used. If warnings are treated as errors, this will break the build; if the call is only for validation, discard the value explicitly.
 // The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(
baseStream: _archive.ArchiveStream,

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1078

  • This browser-only test validates ZipCrypto decryption, but it doesn’t cover creating a ZipCrypto entry on browser. Since this PR changes the ZipCrypto encryption path (header salt generation + password buffer clearing), adding a round-trip create/read assertion here would help prevent regressions.
 using MemoryStream createStream = new();
ZipArchive createArchive = await CreateZipArchive(async, createStream, ZipArchiveMode.Create, leaveOpen: true);
Assert.Throws<PlatformNotSupportedException>(() => createArchive.CreateEntry("aes.txt", Password, ZipEncryptionMethod.Aes256));
await DisposeZipArchive(async, createArchive);
}

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs:626

  • ReadEncryptionSaltIfNeeded now returns early on browser/wasi without populating _aesSalt. In the sync open path (WrapWithDecryptionIfNeeded), AES entries first check _aesSalt is null and throw InvalidDataException(SR.LocalFileHeaderCorrupt), so on browser/wasi this can surface as “corrupt header” instead of the intended PlatformNotSupportedException for WinZip AES. Consider setting a non-null sentinel salt on browser/wasi so the open path reaches the WinZipAesStream stubs and throws PNSE consistently.
 if (!IsAesEncrypted || !_originallyInArchive || OperatingSystem.IsBrowser() || OperatingSystem.IsWasi())
{
return;
}

@alinpahontu2912

Copy link
Copy Markdown
Member

/ba-g failure unrelated to my change

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasmWebAssembly architecturearea-System.IO.Compressionos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm] System.IO.Compression roots System.Security.Cryptography into every trimmed app using ZipArchive (size regression from #122093)

6 participants

@alinpahontu2912@pavelsavara@rzikm@iremyux
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Avoid rooting cryptography through ZipArchive on browser by Copilot · Pull Request #130688 · dotnet/runtime · GitHub
Skip to content

Avoid rooting cryptography through ZipArchive on browser - #130688

Merged
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support
Aug 11, 2026
Merged

Avoid rooting cryptography through ZipArchive on browser#130688
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support

Conversation

CopilotAI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Fixes#130650
which is regression from #122093

Using ZipArchive on browser-wasm unnecessarily retained System.Security.Cryptography, increasing trimmed application size even though WinZip AES is unsupported there.

Changes

  • Exclude WinZip AES implementation files and the cryptography project reference from browser builds.
  • Provide browser-specific WinZip AES stubs that continue throwing PlatformNotSupportedException.
  • Keep ZipCrypto supported by removing its cryptography dependency:
    • Generate header randomness with Guid.NewGuid().
    • Clear pooled password buffers with Array.Clear.
  • Add coverage ensuring browser ZipCrypto remains functional and the wasm dependency closure excludes System.Security.Cryptography.

CopilotAIand others added 2 commits July 14, 2026 13:30
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI self-assigned this Jul 14, 2026
CopilotAI review requested due to automatic review settings July 14, 2026 14:01
CopilotAI removed the request for review from CopilotJuly 14, 2026 14:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:34
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:48
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1072

  • This browser-only test validates ZipCrypto decryption, but this PR also changes browser behavior by swapping in WinZip AES stubs. Consider also asserting that opening the AES-encrypted entry in the same archive throws PlatformNotSupportedException, so the new stub path is exercised on Browser and regressions are caught.
 ZipArchiveEntry entry = archive.GetEntry("hello.txt");
Assert.NotNull(entry);
Assert.Equal(ZipEncryptionMethod.ZipCrypto, entry.EncryptionMethod);
using Stream entryStream = await OpenEntryStream(async, entry, Password);
using StreamReader reader = new(entryStream);

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs:30

  • GetCryptographicallySecureRandomBytes currently forwards to GetRandomBytes, which throws InvalidOperationException on most failures. Since the method name (and the Unix implementation) implies cryptographic RNG semantics, it should throw CryptographicException for non-OOM failures to better match RandomNumberGenerator behavior.
 // BCryptGenRandom with BCRYPT_USE_SYSTEM_PREFERRED_RNG is always cryptographically secure.
internal static unsafe void GetCryptographicallySecureRandomBytes(byte* buffer, int length) =>
GetRandomBytes(buffer, length);

alinpahontu2912and others added 2 commits August 6, 2026 16:50
- Rename the sole BCrypt-backed method in
Interop.BCryptGenRandom.GetRandomBytes.cs to
GetCryptographicallySecureRandomBytes directly, removing the
pass-through alias wrapper (file name kept unchanged).
- Add a short comment at the ZipCryptoStream.Random.cs call site noting
the call is cryptographically secure on all platforms.
- Extend DecryptZipCryptoEntry_Browser to also assert that creating a
WinZip AES-encrypted entry on browser throws PlatformNotSupportedException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c
Keep the original GetRandomBytes name in the BCrypt interop file and
restore GetCryptographicallySecureRandomBytes as a thin wrapper, with a
comment explaining why the wrapper exists: it gives the Windows method
the same name as the Unix crypto-secure API, so shared cross-platform
callers (ZipCryptoStream) reliably get a cryptographically secure
implementation on every platform.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:785

  • keySizeBits is computed but never used in this AES update-mode path. This is dead code and can produce warnings / confusion; it should be removed (the key size was already baked into _derivedAesKeyMaterial).
 // Determine the actual compression method to use
// The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

…rator elsewhere
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:9

  • The WinZipAesKeyMaterial stub is declared as internal readonly struct WinZipAesKeyMaterial; which is not valid C# syntax (types can’t be forward-declared with a trailing semicolon). This will fail to compile on browser builds.
 internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System.IO.Compression.csproj:128

  • System.Security.Cryptography doesn’t target $(NetCoreAppCurrent)-wasi (its csproj only includes windows/unix/android/apple/browser/$(NetCoreAppCurrent)), so keeping this ProjectReference for wasi will break the wasi build. The condition should exclude wasi as well as browser.
 <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Cryptography\src\System.Security.Cryptography.csproj" Condition="'$(TargetPlatformIdentifier)' != 'browser'" />

Comment threadsrc/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:10

  • WinZipAesKeyMaterial is declared with a trailing semicolon, which isn’t valid C# (C# doesn’t support forward-declaring structs). Browser builds will fail to compile this file.
{
internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:786

  • In this AES update-mode branch, int keySizeBits = GetAesKeySizeBits(Encryption); (a few lines above) is assigned but never used. If warnings are treated as errors, this will break the build; if the call is only for validation, discard the value explicitly.
 // The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(
baseStream: _archive.ArchiveStream,

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1078

  • This browser-only test validates ZipCrypto decryption, but it doesn’t cover creating a ZipCrypto entry on browser. Since this PR changes the ZipCrypto encryption path (header salt generation + password buffer clearing), adding a round-trip create/read assertion here would help prevent regressions.
 using MemoryStream createStream = new();
ZipArchive createArchive = await CreateZipArchive(async, createStream, ZipArchiveMode.Create, leaveOpen: true);
Assert.Throws<PlatformNotSupportedException>(() => createArchive.CreateEntry("aes.txt", Password, ZipEncryptionMethod.Aes256));
await DisposeZipArchive(async, createArchive);
}

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs:626

  • ReadEncryptionSaltIfNeeded now returns early on browser/wasi without populating _aesSalt. In the sync open path (WrapWithDecryptionIfNeeded), AES entries first check _aesSalt is null and throw InvalidDataException(SR.LocalFileHeaderCorrupt), so on browser/wasi this can surface as “corrupt header” instead of the intended PlatformNotSupportedException for WinZip AES. Consider setting a non-null sentinel salt on browser/wasi so the open path reaches the WinZipAesStream stubs and throws PNSE consistently.
 if (!IsAesEncrypted || !_originallyInArchive || OperatingSystem.IsBrowser() || OperatingSystem.IsWasi())
{
return;
}

@alinpahontu2912

Copy link
Copy Markdown
Member

/ba-g failure unrelated to my change

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasmWebAssembly architecturearea-System.IO.Compressionos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm] System.IO.Compression roots System.Security.Cryptography into every trimmed app using ZipArchive (size regression from #122093)

6 participants

@alinpahontu2912@pavelsavara@rzikm@iremyux
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Avoid rooting cryptography through ZipArchive on browser by Copilot · Pull Request #130688 · dotnet/runtime · GitHub
Skip to content

Avoid rooting cryptography through ZipArchive on browser - #130688

Merged
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support
Aug 11, 2026
Merged

Avoid rooting cryptography through ZipArchive on browser#130688
alinpahontu2912 merged 20 commits into
mainfrom
copilot/fix-ziparchive-password-support

Conversation

CopilotAI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Fixes#130650
which is regression from #122093

Using ZipArchive on browser-wasm unnecessarily retained System.Security.Cryptography, increasing trimmed application size even though WinZip AES is unsupported there.

Changes

  • Exclude WinZip AES implementation files and the cryptography project reference from browser builds.
  • Provide browser-specific WinZip AES stubs that continue throwing PlatformNotSupportedException.
  • Keep ZipCrypto supported by removing its cryptography dependency:
    • Generate header randomness with Guid.NewGuid().
    • Clear pooled password buffers with Array.Clear.
  • Add coverage ensuring browser ZipCrypto remains functional and the wasm dependency closure excludes System.Security.Cryptography.

CopilotAIand others added 2 commits July 14, 2026 13:30
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI self-assigned this Jul 14, 2026
CopilotAI review requested due to automatic review settings July 14, 2026 14:01
CopilotAI removed the request for review from CopilotJuly 14, 2026 14:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:34
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:48
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotJuly 15, 2026 08:53

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1072

  • This browser-only test validates ZipCrypto decryption, but this PR also changes browser behavior by swapping in WinZip AES stubs. Consider also asserting that opening the AES-encrypted entry in the same archive throws PlatformNotSupportedException, so the new stub path is exercised on Browser and regressions are caught.
 ZipArchiveEntry entry = archive.GetEntry("hello.txt");
Assert.NotNull(entry);
Assert.Equal(ZipEncryptionMethod.ZipCrypto, entry.EncryptionMethod);
using Stream entryStream = await OpenEntryStream(async, entry, Password);
using StreamReader reader = new(entryStream);

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs:30

  • GetCryptographicallySecureRandomBytes currently forwards to GetRandomBytes, which throws InvalidOperationException on most failures. Since the method name (and the Unix implementation) implies cryptographic RNG semantics, it should throw CryptographicException for non-OOM failures to better match RandomNumberGenerator behavior.
 // BCryptGenRandom with BCRYPT_USE_SYSTEM_PREFERRED_RNG is always cryptographically secure.
internal static unsafe void GetCryptographicallySecureRandomBytes(byte* buffer, int length) =>
GetRandomBytes(buffer, length);

alinpahontu2912and others added 2 commits August 6, 2026 16:50
- Rename the sole BCrypt-backed method in
Interop.BCryptGenRandom.GetRandomBytes.cs to
GetCryptographicallySecureRandomBytes directly, removing the
pass-through alias wrapper (file name kept unchanged).
- Add a short comment at the ZipCryptoStream.Random.cs call site noting
the call is cryptographically secure on all platforms.
- Extend DecryptZipCryptoEntry_Browser to also assert that creating a
WinZip AES-encrypted entry on browser throws PlatformNotSupportedException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c
Keep the original GetRandomBytes name in the BCrypt interop file and
restore GetCryptographicallySecureRandomBytes as a thin wrapper, with a
comment explaining why the wrapper exists: it gives the Windows method
the same name as the Unix crypto-secure API, so shared cross-platform
callers (ZipCryptoStream) reliably get a cryptographically secure
implementation on every platform.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 52519a8a-ff2e-46fc-97c8-77e133223f9c

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:785

  • keySizeBits is computed but never used in this AES update-mode path. This is dead code and can produce warnings / confusion; it should be removed (the key size was already baked into _derivedAesKeyMaterial).
 // Determine the actual compression method to use
// The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

…rator elsewhere
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:9

  • The WinZipAesKeyMaterial stub is declared as internal readonly struct WinZipAesKeyMaterial; which is not valid C# syntax (types can’t be forward-declared with a trailing semicolon). This will fail to compile on browser builds.
 internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System.IO.Compression.csproj:128

  • System.Security.Cryptography doesn’t target $(NetCoreAppCurrent)-wasi (its csproj only includes windows/unix/android/apple/browser/$(NetCoreAppCurrent)), so keeping this ProjectReference for wasi will break the wasi build. The condition should exclude wasi as well as browser.
 <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Cryptography\src\System.Security.Cryptography.csproj" Condition="'$(TargetPlatformIdentifier)' != 'browser'" />

Comment threadsrc/libraries/System.IO.Compression/src/System.IO.Compression.csproj Outdated
Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/libraries/System.IO.Compression/src/System/IO/Compression/WinZipAes.PlatformNotSupported.cs:10

  • WinZipAesKeyMaterial is declared with a trailing semicolon, which isn’t valid C# (C# doesn’t support forward-declaring structs). Browser builds will fail to compile this file.
{
internal readonly struct WinZipAesKeyMaterial;

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.Async.cs:786

  • In this AES update-mode branch, int keySizeBits = GetAesKeySizeBits(Encryption); (a few lines above) is assigned but never used. If warnings are treated as errors, this will break the build; if the call is only for validation, discard the value explicitly.
 // The AES extra field stores the real compression method
bool useDeflate = _compressionLevel != CompressionLevel.NoCompression;
Stream encryptionStream = WinZipAesStream.Create(
baseStream: _archive.ArchiveStream,

src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs:1078

  • This browser-only test validates ZipCrypto decryption, but it doesn’t cover creating a ZipCrypto entry on browser. Since this PR changes the ZipCrypto encryption path (header salt generation + password buffer clearing), adding a round-trip create/read assertion here would help prevent regressions.
 using MemoryStream createStream = new();
ZipArchive createArchive = await CreateZipArchive(async, createStream, ZipArchiveMode.Create, leaveOpen: true);
Assert.Throws<PlatformNotSupportedException>(() => createArchive.CreateEntry("aes.txt", Password, ZipEncryptionMethod.Aes256));
await DisposeZipArchive(async, createArchive);
}

Co-authored-by: alinpahontu2912 <56953855+alinpahontu2912@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/libraries/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs:626

  • ReadEncryptionSaltIfNeeded now returns early on browser/wasi without populating _aesSalt. In the sync open path (WrapWithDecryptionIfNeeded), AES entries first check _aesSalt is null and throw InvalidDataException(SR.LocalFileHeaderCorrupt), so on browser/wasi this can surface as “corrupt header” instead of the intended PlatformNotSupportedException for WinZip AES. Consider setting a non-null sentinel salt on browser/wasi so the open path reaches the WinZipAesStream stubs and throws PNSE consistently.
 if (!IsAesEncrypted || !_originallyInArchive || OperatingSystem.IsBrowser() || OperatingSystem.IsWasi())
{
return;
}

@alinpahontu2912

Copy link
Copy Markdown
Member

/ba-g failure unrelated to my change

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasmWebAssembly architecturearea-System.IO.Compressionos-browserBrowser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wasm] System.IO.Compression roots System.Security.Cryptography into every trimmed app using ZipArchive (size regression from #122093)

6 participants

@alinpahontu2912@pavelsavara@rzikm@iremyux