fix(releases): reject malformed PE inputs before signing and packaging #24

Closed
opened 2026-10-10 22:15:53 +00:00 by KofTwentyTwo · 1 comment
KofTwentyTwo commented 2026-10-10 22:15:53 +00:00 (Migrated from github.com)

Problem

The production New-WindowsSigningCatalog records preserved dependency hashes without checking whether their original .exe/.dll PE headers parse. A dependency already malformed before catalog preparation can retain identical bytes through packaging and pass preservation comparisons. The installed smoke harness has this source check; production catalog preparation does not.

Confirmed offline using a real AppKit owned DLL plus a 128-byte zeroed BrokenDependency.dll, with ExpectedSubject and PreserveOtherBinaries configured: catalog preparation succeeded and recorded the malformed dependency. Evidence: artifacts/readiness-issues/catalog-pe-proof-187dc7671bb04713ad779bf03357c113/. No Azure calls, signing or publication occurred. This is distinct from #22's resolved missing/changed archive-byte checks; the cause of earlier corruption remains unknown.

Acceptance

  • Reject malformed owned or preserved .exe/.dll inputs before writing signing catalogs or invoking Azure/signing/packing.
  • Keep format-specific behavior: MSI/MSIX are not PE executable images; later signature/package validation remains required.
  • Keep root AppKit and shared helper source aligned, and ensure prepared workflows reference the helper revision containing this check.
  • Add real valid-PE and malformed owned/dependency regression cases; run relevant script analysis and signing tests.
  • Update release/threat-model evidence and retain rollout/signature proof requirements in #12/#20.

Substantial AI assistance: Codex (GPT-6). No original sibling checkout or existing public release was modified.

## Problem The production `New-WindowsSigningCatalog` records preserved dependency hashes without checking whether their original `.exe`/`.dll` PE headers parse. A dependency already malformed before catalog preparation can retain identical bytes through packaging and pass preservation comparisons. The installed smoke harness has this source check; production catalog preparation does not. Confirmed offline using a real AppKit owned DLL plus a 128-byte zeroed `BrokenDependency.dll`, with `ExpectedSubject` and `PreserveOtherBinaries` configured: catalog preparation succeeded and recorded the malformed dependency. Evidence: `artifacts/readiness-issues/catalog-pe-proof-187dc7671bb04713ad779bf03357c113/`. No Azure calls, signing or publication occurred. This is distinct from #22's resolved missing/changed archive-byte checks; the cause of earlier corruption remains unknown. ## Acceptance - Reject malformed owned or preserved `.exe`/`.dll` inputs before writing signing catalogs or invoking Azure/signing/packing. - Keep format-specific behavior: MSI/MSIX are not PE executable images; later signature/package validation remains required. - Keep root AppKit and shared helper source aligned, and ensure prepared workflows reference the helper revision containing this check. - Add real valid-PE and malformed owned/dependency regression cases; run relevant script analysis and signing tests. - Update release/threat-model evidence and retain rollout/signature proof requirements in #12/#20. Substantial AI assistance: Codex (GPT-6). No original sibling checkout or existing public release was modified.
KofTwentyTwo commented 2026-10-10 22:24:38 +00:00 (Migrated from github.com)

Implemented and verified the scoped production source-input gate in signed local commits:

  • AppKit bbf7efdba8e3d3a4cfe141923153dce53dc11fda.
  • Shared helper 4a7f028976163cb80730126eda1b029005803325.
  • Prepared shared workflows 2fdf22c48485c55248c59d195aec7b3556f68f02, referencing that exact helper snapshot.

Catalog creation now parses owned and preserved .exe/.dll headers before output. MSI/MSIX use their later format-specific checks; excluded, non-preserved files do not interfere with scoped NuGet signing. Original third-party signatures remain untouched. Initial test fixtures now use real PE bytes; different culture payloads retain different bytes.

The exact previously accepted malformed dependency is rejected before any catalog or manifest exists. Evidence: artifacts/readiness-issues/catalog-pe-rejection-f72a44f75aee484a8f56ba1455544f86/result.json. AppKit's 40 script cases and shared signing/wrapper 35 cases pass. Changed-source PowerShell checks passed in fresh processes after one analyzer internal exception; required hooks, workflow syntax/offline security and shared-policy Markdown checks passed. All commit signatures verified. Helper source blob matches the workflow reference.

Release guides and both threat models now explain this boundary. Closing the scoped source-validation implementation criteria; real Azure authorization/signatures and reviewed builder deployment remain #12/#20. The referenced helper is still explicitly unreleased preparation; consumers remain blocked and no unpublished builder was pinned. No push, merge, release, settings/Azure change or login retry occurred. The historical corruption cause remains unknown.

Implemented and verified the scoped production source-input gate in signed local commits: - AppKit `bbf7efdba8e3d3a4cfe141923153dce53dc11fda`. - Shared helper `4a7f028976163cb80730126eda1b029005803325`. - Prepared shared workflows `2fdf22c48485c55248c59d195aec7b3556f68f02`, referencing that exact helper snapshot. Catalog creation now parses owned and preserved `.exe`/`.dll` headers before output. MSI/MSIX use their later format-specific checks; excluded, non-preserved files do not interfere with scoped NuGet signing. Original third-party signatures remain untouched. Initial test fixtures now use real PE bytes; different culture payloads retain different bytes. The exact previously accepted malformed dependency is rejected before any catalog or manifest exists. Evidence: `artifacts/readiness-issues/catalog-pe-rejection-f72a44f75aee484a8f56ba1455544f86/result.json`. AppKit's 40 script cases and shared signing/wrapper 35 cases pass. Changed-source PowerShell checks passed in fresh processes after one analyzer internal exception; required hooks, workflow syntax/offline security and shared-policy Markdown checks passed. All commit signatures verified. Helper source blob matches the workflow reference. Release guides and both threat models now explain this boundary. Closing the scoped source-validation implementation criteria; real Azure authorization/signatures and reviewed builder deployment remain #12/#20. The referenced helper is still explicitly unreleased preparation; consumers remain blocked and no unpublished builder was pinned. No push, merge, release, settings/Azure change or login retry occurred. The historical corruption cause remains unknown.
Sign in to join this conversation.