Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 3, 2025

Implementation of DoNotUnpack via FileSignInfo and FileExtensionSignInfo

This PR implements the DoNotUnpack feature for SignTool that allows containers to be signed without unpacking their contents. The feature is configured via FileSignInfo and FileExtensionSignInfo metadata.

Changes Made:

Core Implementation:

  • SignInfo.cs: Added DoNotUnpack property and WithDoNotUnpack() method
  • FileSignInfoEntry.cs: Certificate name is now optional - can specify DoNotUnpack without a certificate
  • ExplicitSignInfoKey.cs (renamed from ExplicitCertificateKey): Represents the entity being signed rather than just certificate correlation, supports setting properties like DoNotUnpack independently of certificates
  • SignToolTask.cs:
    • Parse DoNotUnpack metadata from FileExtensionSignInfo
    • Parse DoNotUnpack metadata from FileSignInfo (via FileSignInfoEntry type)
    • Fixed validation: Certificate is only required when DoNotUnpack is NOT set
  • Configuration.cs:
    • Updated to use FileSignInfoEntry for file sign info
    • DoNotUnpack is determined from SignInfo with proper precedence (FileSignInfo > FileExtensionSignInfo)
    • Updated comments to clarify that mappings include DoNotUnpack data
    • Logic allows setting DoNotUnpack without specifying a certificate
  • FileSignInfo.cs:
    • ShouldRepack now uses SignInfo.DoNotUnpack
    • Updated ToString() to include DoNotUnpack info when file has signable parts and DoNotUnpack is true

Tests:

  • ContainerSigningWithDoNotUnpackViaFileSignInfo:
    • Tests DoNotUnpack on top-level container without certificate (uses default from extension)
    • Tests DoNotUnpack on nested container with certificate while allowing top-level to unpack
  • ContainerSigningWithDoNotUnpackViaFileExtensionSignInfo:
    • Tests DoNotUnpack via extension for all .nupkg files

Usage Examples:

Via FileSignInfo (per-file) with certificate:

<FileSignInfo Include="dotnet-sdk-source.tar.gz" CertificateName="LinuxSign" DoNotUnpack="true" />

Via FileSignInfo (per-file) without certificate:

<FileSignInfo Include="dotnet-sdk-source.tar.gz" DoNotUnpack="true" />

Via FileExtensionSignInfo (per-extension):

<FileExtensionSignInfo Include=".tar.gz" CertificateName="LinuxSign" DoNotUnpack="true" />

Via FileExtensionSignInfo without certificate:

<FileExtensionSignInfo Include=".tar.gz" DoNotUnpack="true" />

Precedence:

  • FileSignInfo takes precedence over FileExtensionSignInfo for DoNotUnpack value
  • When DoNotUnpack is set without a certificate, the file uses the default certificate from FileExtensionSignInfo
  • Certificate is only required when DoNotUnpack is NOT set

Testing:

  • All 60+ existing tests pass
  • New tests verify both FileSignInfo and FileExtensionSignInfo approaches
  • Tests cover scenarios with and without certificates
  • Tests verify nested container behavior (top-level vs nested DoNotUnpack settings)
  • Build completes successfully on .NET 10.0 and .NET Framework 4.7.2
Original prompt

This section details on the original issue you should resolve

<issue_title>Allow Signing of Containers Without Unpacking</issue_title>
<issue_description>Currently, when we attempt to sign containers using SignTool, the process unpacks the container and signs artifacts inside them. For some containers, such as the source-built source archives, this leads to the risk of signing artifacts, like binaries, that were checked into the repo. We need to add a feature to SignTool that allows signing of the top-level container without unpacking.</issue_description>

<agent_instructions>SignTool is in https://github.com/dotnet/arcade/tree/main/src/Microsoft.DotNet.SignTool. As part of this work, also add some unit tests in https://github.com/dotnet/arcade/blob/main/src/Microsoft.DotNet.SignTool.Tests/SignToolTests.cs for this feature.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Add feature to sign top-level containers without unpacking Add DoNotUnpack flag to sign containers without extracting contents Dec 3, 2025
Copilot AI requested a review from ellahathaway December 3, 2025 18:12
@mmitche
Copy link
Member

mmitche commented Dec 4, 2025

@copilot Because a top-level file could be duplicated within other archives (e.g. an MSI at the top level as well as within a VS.* nupkg), I think a better way to implement this is via a new bit of metadata on FileSignInfo and other certificate specification metadata.

Copy link
Contributor Author

Copilot AI commented Dec 4, 2025

@copilot Because a top-level file could be duplicated within other archives (e.g. an MSI at the top level as well as within a VS.* nupkg), I think a better way to implement this is via a new bit of me...

I understand the concern about duplicated files. To clarify the intended design: should the DoNotUnpack behavior be specified via FileSignInfo (per-file name) or FileExtensionSignInfo (per-extension like .tar.gz)? For example, would the configuration look like:

<FileSignInfo Include="dotnet-sdk-source.tar.gz" CertificateName="LinuxSign" DoNotUnpack="true" />

Or via extension:

<FileExtensionSignInfo Include=".tar.gz" CertificateName="LinuxSign" DoNotUnpack="true" />

This would allow the same file to be signed without unpacking when it appears at the top level, but still be unpacked when nested in another container. Please confirm and I'll refactor the implementation accordingly.

Copilot AI requested a review from mmitche December 4, 2025 17:14
@ellahathaway
Copy link
Member

I understand the concern about duplicated files. To clarify the intended design: should the DoNotUnpack behavior be specified via FileSignInfo (per-file name) or FileExtensionSignInfo (per-extension like .tar.gz)? For example, would the configuration look like:

<FileSignInfo Include="dotnet-sdk-source.tar.gz" CertificateName="LinuxSign" DoNotUnpack="true" />

Or via extension:

<FileExtensionSignInfo Include=".tar.gz" CertificateName="LinuxSign" DoNotUnpack="true" />

This would allow the same file to be signed without unpacking when it appears at the top level, but still be unpacked when nested in another container. Please confirm and I'll refactor the implementation accordingly.

@copilot - please implement this for both file name (FileSignInfo) and file extension (FileExtensionSignInfo).

Copy link
Contributor Author

Copilot AI commented Dec 4, 2025

I understand the concern about duplicated files. To clarify the intended design: should the DoNotUnpack behavior be specified via FileSignInfo (per-file name) or FileExtensionSignInfo (per-ext...

Implemented DoNotUnpack for both FileSignInfo (per-file name) and FileExtensionSignInfo (per-extension). The implementation adds a new FileSignInfoEntry class to hold both certificate name and DoNotUnpack flag, and extends SignInfo to carry the DoNotUnpack state from extension-based configuration.

Usage examples:

<!-- Per-file via FileSignInfo -->
<FileSignInfo Include="dotnet-sdk-source.tar.gz" CertificateName="LinuxSign" DoNotUnpack="true" />

<!-- Per-extension via FileExtensionSignInfo -->
<FileExtensionSignInfo Include=".tar.gz" CertificateName="LinuxSign" DoNotUnpack="true" />

Added tests for both approaches. Commit: e7a45b0

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • securitytools.pkgs.visualstudio.com
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.23.6/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp /opt/hostedtoolcache/CodeQL/2.23.6/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copy link
Member

@ellahathaway ellahathaway left a comment

Choose a reason for hiding this comment

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

@copilot

Please refactor ExplicitCertificateKey to a name that more clearly describes its actual use, such as ExplicitSignInfoKey (or something similar). The current name implies a direct relationship to the certificate, but with recent changes, FileSignInfo can specify properties like DoNotUnpack without necessarily having a certificate. In other words, the key should represent the entity being signed (e.g., file name, path, or attributes) rather than its certificate correlation.

For example, we want to support scenarios like:

<FileSignInfo Name="MyPackage1.nupkg" Certificate="Microsoft400"/>
<FileSignInfo Name="MyPackage2.nupkg" DoNotUnpack="true"/>
<FileSignInfo Name="MyPackage3.nupkg" Certificate="Microsoft400" DoNotUnpack="true"/>

where FileSignInfo entries can set properties independently of a certificate. The dictionary key type should reflect this broader use case, not just certificate mapping.

Copy link
Contributor Author

Copilot AI commented Dec 12, 2025

@copilot

Please refactor ExplicitCertificateKey to a name that more clearly describes its actual use, such as ExplicitSignInfoKey (or something similar). The current name implies a direct relat...

Refactored ExplicitCertificateKey to ExplicitSignInfoKey to better reflect its purpose. The key now represents the entity being signed (file name, attributes) rather than just certificate correlation. Added documentation clarifying it can specify signing properties like DoNotUnpack independently of certificates. Commit: dfa9bcc

Copilot AI requested a review from ellahathaway December 12, 2025 18:12
@ellahathaway ellahathaway marked this pull request as ready for review December 12, 2025 19:09
Copilot AI requested a review from mmitche December 15, 2025 18:59
Copy link
Member

@mmitche mmitche left a comment

Choose a reason for hiding this comment

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

I think the logic looks all correct here

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow Signing of Containers Without Unpacking

4 participants