Skip to content

Do not sign ASP.NET Core static web assets in containers - #1055

Open
ChatchawanIllyes wants to merge 2 commits into
dotnet:mainfrom
ChatchawanIllyes:static-web-assets-1045
Open

Do not sign ASP.NET Core static web assets in containers#1055
ChatchawanIllyes wants to merge 2 commits into
dotnet:mainfrom
ChatchawanIllyes:static-web-assets-1045

Conversation

@ChatchawanIllyes

Copy link
Copy Markdown

Fixes #1045

Problem

Packages produced by the ASP.NET Core SDK (Blazor and Razor class libraries) carry their browser assets in a staticwebassets directory and record each asset's integrity hash at pack time in build/Microsoft.AspNetCore.StaticWebAssets.props.

.js is in the signable extension list because Windows Script Host scripts are .js, so recursing into such a package signs its .js assets. That changes the files, invalidates the recorded hashes, and consuming applications fail with an integrity conflict. The workaround reported in #1045 was --recurse-containers false, which gives up signing the package contents entirely.

Change

When recursing into a container, AggregatingSigner now skips the files in a package's staticwebassets directory and logs a warning naming each skipped file.

Detection is convention-based and scoped to the package that declares the assets:

  • A package is recognized by a Microsoft.AspNetCore.StaticWebAsset*.props file in its build, buildTransitive, or buildMultiTargeting directory. The wildcard also covers Microsoft.AspNetCore.StaticWebAssetEndpoints.props (.NET 9 and later).
  • Only that package's own staticwebassets directory is skipped --- a staticwebassets directory elsewhere in the container is not.
  • Files elsewhere in the package are unaffected, including .js files outside of staticwebassets, so genuine Windows Script Host scripts are still signed.

Filtering applies only when no file list was provided. A caller who explicitly listed files has already stated an intent, so static web assets can still be signed by listing them with --file-list.

The new IStaticWebAssetFilter works on the file paths already enumerated from the container, so it adds no IContainer.GetFiles(...) calls.

Notes

  • This changes default behavior: files that were previously signed inside static web asset packages are now skipped, with a warning. Signing a file that a browser integrity-checks is never the intent, so this seemed preferable to a warning-only change, but I am happy to switch to warning-only or to add an opt-out option if you would rather not change the default.
  • One new resource string, with the .xlf files updated by the build.

Testing

  • New StaticWebAssetFilterTests covering the marker file locations and names, non-.js assets (.wasm, .dll), a .js file outside staticwebassets, a similarly named directory, case insensitivity, and the warning.
  • New AggregatingSignerTests cases for a .nupkg container with and without a file list.
  • I developed this on macOS, where Sign.Core.Test compiles but cannot run (the projects are win-x64 and Sign.TestInfrastructure needs mage.exe). I verified the new and existing AggregatingSigner tests --- 55 in total --- by compiling the same sources into a scratch net8.0 project and running them locally; they all pass. CI is the first Windows run.

🤖 Generated with Claude Code

@ChatchawanIllyes
ChatchawanIllyes requested a review from a team as a code owner August 11, 2026 02:21
@ChatchawanIllyes

Copy link
Copy Markdown
Author

@dotnet-policy-service agree

@kartheekp-ms

Copy link
Copy Markdown
Contributor

@ChatchawanIllyes please rebase since we migrated tests from Moq to NSubstitute.

ChatchawanIllyes and others added 2 commits August 15, 2026 12:32
Packages produced by the ASP.NET Core SDK carry their browser assets in a
staticwebassets directory and record each asset's integrity hash at pack time
in build/Microsoft.AspNetCore.StaticWebAssets.props.  Because .js is signable
(Windows Script Host scripts are .js), recursing into such a package signs its
.js assets, which changes them and invalidates the recorded hashes.  Consuming
applications then fail with an integrity conflict.

When recursing into a container, skip the files in a package's staticwebassets
directory and log a warning for each one.  A package is recognized by a
Microsoft.AspNetCore.StaticWebAsset*.props file in its build, buildTransitive,
or buildMultiTargeting directory, and only that package's staticwebassets
directory is skipped.  Files elsewhere in the package, including .js files
outside of staticwebassets, are unaffected.

Filtering is skipped when the caller provides a file list, so static web assets
can still be signed by listing them explicitly with --file-list.

Fixes dotnet#1045

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
SignerTests builds its own service collection, so AggregatingSigner could not
be activated there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

Somehow distinguish .js files that are static web assets from those that are Windows Script Host scripts

2 participants