Repository navigation
OPS-157454: Restore the main build with warnings-as-errors kept on - #2
Conversation
main failed with about 2,800 errors once 91f6bac turned TreatWarningsAsErrors back on. Fixed without switching it off: - Nullable reference types: the vendored projects use <Nullable>annotations</Nullable> (the library and tests already carry some `?` annotations, so `disable` would give CS8632) and the samples use disable. The library's nullability metadata is unchanged from 10.1.9. - CA1416: System.Drawing-dependent public APIs are marked [SupportedOSPlatform("windows")] (AutoFitColumns/AutoFit, AddPicture(Image|FileInfo), ExcelPicture.Image/ImageFormat, SetFromFont, header/footer InsertPicture, background image, VML picture Image). Paths reachable from platform-neutral code are guarded: loading or cross-package copying a System.Drawing picture throws PlatformNotSupportedException off Windows, where it already failed. - CA2022: unchecked Stream.Read calls use ReadAtLeast(..., throwOnEndOfStream: false), which handles short reads and keeps the old no-throw behaviour at end of stream. - WinZipAes moves from RijndaelManaged to Aes and from the Rfc2898DeriveBytes ctor to Rfc2898DeriveBytes.Pbkdf2 (SHA1, same iterations, output split the same way); both verified byte-identical. VBA signature certificates use X509CertificateLoader. Uri.EscapeUriString is replaced by a local helper with identical output, verified on 28,000+ inputs. - CA2200/CS0168 rethrow, CS8981 alias, CS8794 always-true pattern (behaviour kept), bad XML doc params/crefs. - CS1591 suppressed for the library only (2,211 undocumented vendored members); test and sample projects no longer generate documentation files. - Re-applies three fixes from 070eab9 that 91f6bac reverted: no MIT licence expression on the LGPL package (NU5033), no Microsoft.Testing.Platform runner in global.json, and SampleWebApp (now on WebApplication hosting, so no obsolete APIs). SampleApp moves to Microsoft.Data.SqlClient. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 4 |
| Duplication | 0 |
AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Pull Request Overview
While this PR successfully addresses the build restoration and modernization of cryptographic APIs, it is currently not up to standards according to Codacy and contains high-risk logic flaws. The implementation of 'Stream.ReadAtLeast' to address CA2022 warnings is incorrect in multiple locations; by suppressing end-of-stream exceptions without verifying the number of bytes actually read, the code risks writing uninitialized data to output streams, leading to file corruption.
Several security concerns remain, including the use of insecure cipher modes and the exposure of developer exception pages in production environments. Furthermore, critical logic changes—such as the custom URI escaping helper and new cryptographic loaders—lack internal automated test coverage. Given that existing CI tests are failing or not running, these changes pose a significant regression risk.
About this PR
- Critical logic changes regarding cryptography and URI escaping were verified using external harnesses. These tests should be integrated into the project's test suite to prevent future regressions, especially as the current CI environment is reported to have existing test failures.
Test suggestions
- Found recommended test scenario: Verify AutoFitColumns correctly calculates widths on Windows.
- Found recommended test scenario: Verify ExcelPicture can be added, sized, and saved correctly using System.Drawing on Windows.
- Found recommended test scenario: Verify copying worksheets with pictures between packages correctly handles image parts.
- Missing recommended test scenario: Ensure ReadAtLeast correctly handles potential short reads when decrypting data blocks.
- Missing recommended test scenario: Verify WinZip AES encryption/decryption remains compatible with 128, 192, and 256-bit keys using the new Aes implementation.
- Missing recommended test scenario: Verify VBA signature loading using X509CertificateLoader produces identical results to the legacy implementation.
- Missing recommended test scenario: Verify the custom URI escaping helper produces identical output to the obsolete Uri.EscapeUriString across ASCII and non-ASCII inputs.
- Missing recommended test scenario: Confirm that Windows-only drawing APIs throw PlatformNotSupportedException when called on non-Windows platforms.
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Missing recommended test scenario: Ensure ReadAtLeast correctly handles potential short reads when decrypting data blocks.
2. Missing recommended test scenario: Verify WinZip AES encryption/decryption remains compatible with 128, 192, and 256-bit keys using the new Aes implementation.
3. Missing recommended test scenario: Verify VBA signature loading using X509CertificateLoader produces identical results to the legacy implementation.
4. Missing recommended test scenario: Verify the custom URI escaping helper produces identical output to the obsolete Uri.EscapeUriString across ASCII and non-ASCII inputs.
5. Missing recommended test scenario: Confirm that Windows-only drawing APIs throw PlatformNotSupportedException when called on non-Windows platforms.
Low confidence findings
- The custom 'EscapeUriString' helper is currently private to 'ZipPackageRelationshipBase'. Consider moving this to a shared utility class to avoid logic duplication if URI escaping is required elsewhere in the library.
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
| }; | ||
| _aesCipher = Aes.Create(); | ||
| _aesCipher.KeySize = keySizeInBits; // 128, 192, 256 | ||
| _aesCipher.Mode = CipherMode.ECB; |
There was a problem hiding this comment.
🔴 HIGH RISK
The use of 'CipherMode.ECB' is insecure. While likely used to implement a custom AES-CTR stream for ZIP compatibility, please provide a security justification in the comments or evaluate if modern authenticated encryption APIs can be used.
| } | ||
| } No newline at end of file | ||
| var app = builder.Build(); | ||
| app.UseDeveloperExceptionPage(); |
There was a problem hiding this comment.
🔴 HIGH RISK
Wrap 'app.UseDeveloperExceptionPage()' in an environment check (e.g., 'if (app.Environment.IsDevelopment())') to prevent sensitive data disclosure in production environments.
| if (_InputUsesZip64) size += 8; | ||
| var Descriptor = new byte[size]; | ||
| input.Read(Descriptor, 0, size); | ||
| input.ReadAtLeast(Descriptor.AsSpan(0, size), size, throwOnEndOfStream: false); |
There was a problem hiding this comment.
🔴 HIGH RISK
Ignoring the return value when throwOnEndOfStream is false can cause uninitialized bytes to be written to the output archive. Use the default behavior to ensure an EndOfStreamException is raised if the input descriptor is truncated.
| var decryptedData = new byte[size]; | ||
|
|
||
| cryptoStream.Read(decryptedData, 0, (int)size); | ||
| cryptoStream.ReadAtLeast(decryptedData.AsSpan(0, (int)size), (int)size, throwOnEndOfStream: false); |
There was a problem hiding this comment.
🔴 HIGH RISK
Using throwOnEndOfStream: false without verifying the returned byte count leads to silent corruption when the truncated buffer is written to the document. Use the default true to ensure an exception is thrown if the required data is missing.
| throw new BadReadException(String.Format(" Bad signature (0x{0:X8}) looking for ZIP64 EoCD Record at position 0x{1:X8}", datum, s.Position)); | ||
|
|
||
| s.Read(block, 0, 8); | ||
| s.ReadAtLeast(block.AsSpan(0, 8), 8, throwOnEndOfStream: false); |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Failing to read the full 8 bytes of metadata will result in BitConverter producing an incorrect value. It is safer to use the default throwOnEndOfStream: true here so that the parser fails immediately on a truncated file.
|
|
||
| if (obj is double) return obj; | ||
| if (obj.IsNumeric()) return util.ConvertUtil.GetValueDouble(obj); | ||
| if (obj.IsNumeric()) return Utils.ConvertUtil.GetValueDouble(obj); |
There was a problem hiding this comment.
⚪ LOW RISK
Nitpick: Enclose the 'if' block statement in curly braces to satisfy code style requirements and prevent maintenance errors.
Only show the developer exception page in Development in SampleWebApp, and mark WinZip AES's ECB use as intended: it is the block primitive for CTR mode, with HMAC-SHA1 for integrity. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Merged via #1: this branch was merged into fix/codeql-full-clone so the combined change got a fully green run (build, Analyze (csharp), CodeQL, Codacy). This PR's own Analyze could only fail on the shallow clone that #1 fixes. The CodeQL cs/ecb-encryption alert on WinZipAes was dismissed as a false positive (AES-CTR keystream). |
Fixes the broken
mainbuild for OPS-157454.TreatWarningsAsErrorsstays on; each error class is fixed rather than suppressed, with one exception (CS1591, below).Approach
<Nullable>annotations</Nullable>. The source already has 88?annotations, whichdisableturns into CS8632 errors.annotationsturns the warnings off and keeps the nullability metadata consumers see the same as in 10.1.9. Samples:disable.[SupportedOSPlatform("windows")]on the System.Drawing-dependent members, not the assembly. Paths reachable from platform-neutral code are guarded (see below).ReadAtLeast(buffer, n, throwOnEndOfStream: false): short reads are now completed, full reads behave as before, and a stream that ends early still doesn't throw, as before.RijndaelManagedtoAes(128-bit block, ECB, no padding, same key) and theRfc2898DeriveBytesconstructor toRfc2898DeriveBytes.Pbkdf2(SHA1, same iterations, one output split into key / MAC key / verifier). Both checked byte-identical with a harness for 128/192/256-bit keys.X509CertificateLoader.LoadCertificate. The VBA signature's certificate-store entry 0x20 holds a DER X.509 certificate.Target(OriginalString) on save, soEscapeDataStringwould change saved files (it escapes:and/). Replaced with a private helper that gives the same output asUri.EscapeUriString, checked equal on 28,000+ inputs, including non-ASCII and lone surrogates.throw;, unused variables removed,utilalias renamed toUtils.is not Equal or not Insideis always true (as was upstream's!= || !=). Simplified to the same behaviour: the worksheet dimension is used whenever there is one.<param>tags and unresolvable crefs corrected.NoWarn), for the same reason as nullability: vendored members were never documented. Test and sample projects simply stop generating XML docs.The same commit also restores three fixes from 070eab9 that 91f6bac reverted. All three block the build or tests:
PackageLicenseExpression=MIT(NU5033 pack failure, and it misdeclared an LGPL package);Microsoft.Testing.Platformrunner fromglobal.json(the test project uses VSTest);ImplicitUsingsdisabled again, and the sample moved toWebApplicationhosting, because its obsoleteWebHostBuilder/IHostingEnvironment/UseMvcWithDefaultRouteare now errors. SampleApp moves from obsoleteSystem.Data.SqlClienttoMicrosoft.Data.SqlClient7.1.1 (note: that package defaults toEncrypt=true).Consumer-visible change
These public APIs are now marked Windows-only. A consumer targeting
net10.0that calls them gets a CA1416 warning, which becomes an error if the consumer treats warnings as errors:ExcelRangeBase.AutoFitColumns(*),ExcelColumn.AutoFit(*),ExcelDrawings.AddPicture(string, Image[, Uri])/AddPicture(string, FileInfo[, Uri]),ExcelPicture.Image,ExcelPicture.ImageFormat,ExcelFont/ExcelFontXml/ExcelTextFont.SetFromFont,ExcelHeaderFooterText.InsertPicture(*),ExcelBackgroundImage.Image/SetFromFile,ExcelVmlDrawingPicture.Image.All of them already failed off Windows, because System.Drawing.Common 10 throws there. The byte-array
AddPicturepath stays platform-neutral.Guarded rather than annotated, because platform-neutral code reaches them: loading an existing System.Drawing picture and copying a worksheet with such a picture to another package now throw
PlatformNotSupportedExceptionoff Windows. Previously the first threw System.Drawing's own exception and the second threw aNullReferenceException.ExcelPicture.SetSize/Disposetake the non-image path off Windows, whereImageis always null.Verification
dotnet build -c Release(whole solution,--no-incremental): 0 errors on Windows.dotnet packsucceeds.origin/main(built withTreatWarningsAsErrors=false), excludingDateFunctionsWorkWithDifferentCultureDateFormats_*, which crashes the test host on both: 1158 passed, 11 failed, 214 skipped on both, with the same 11 failures (missingWorkbookstest data and R1C1 tests).VBAerrortests pass. The encryption and VBA-signing tests are all[Ignore]d upstream, and no test covers WinZipAes, so those changes were verified with the equivalence harness described above.🤖 Generated with Claude Code