nuxt-security icon indicating copy to clipboard operation
nuxt-security copied to clipboard

SRI applied incorrectly to <link rel="preload|modulepreload">

Open MinakoKitani opened this issue 3 months ago • 2 comments

Environment

- Operating System: `Windows`
- Node Version:     `v22.12.0`
- Nuxt Version:     `4.0.3`
- Nitro Version:    `2.12.4`
- Package Manager:  `[email protected]`

Nuxt Security Version

2.2.0

Default setup used?

Yes, the bug happens even if the security option is not customized

Security options

security: {
      headers: {
        crossOriginResourcePolicy: false,
        crossOriginOpenerPolicy: false,
        crossOriginEmbedderPolicy: false,
        contentSecurityPolicy: {
          'base-uri': false,
          'font-src': false,
          'form-action': false,
          'frame-ancestors': false,
          'img-src': false,
          'object-src': false,
          'script-src-attr': false,
          'style-src': false,
          'script-src': cspScriptSrc,
          'upgrade-insecure-requests': false,
        },
        originAgentCluster: false,
        referrerPolicy: false,
        strictTransportSecurity: false,
        xContentTypeOptions: false,
        xDNSPrefetchControl: false,
        xDownloadOptions: false,
        xFrameOptions: false,
        xPermittedCrossDomainPolicies: false,
        xXSSProtection: false,
        permissionsPolicy: false,
      },
      requestSizeLimiter: false,
      rateLimiter: false,
      xssValidator: false,
      corsHandler: false,
      allowedMethodsRestricter: false,
      hidePoweredBy: false,
      basicAuth: false,
      nonce: false,
      removeLoggers: false,
      ssg: false,
    },

Reproduction

nitro: { esbuild: { options: { target: 'esnext', }, }, prerender: { crawlLinks: false, routes: ['/'], ignore: [], }, },

Description

When enabling SRI in nuxt-security, it seems that and tags are also being matched by the regex in runtime/nitro/plugins/20-subresourceIntegrity.js:

const LINK_RE = /<link((?=[^>]+\brel="(?:stylesheet|preload|modulepreload)")(?=[^>]+\bhref="([^"]+)")(?![^>]+\bintegrity="[\w-+/=]+")[^>]+)>/g;

This causes integrity attributes to be injected into preload and modulepreload links. However, according to the HTML spec and current browser implementations, Subresource Integrity is not supported for preload/modulepreload links, and integrity attributes there are ignored. Reference: WHATWG Fetch Spec

Additional context

Image Image

Logs

The integrity attribute is currently ignored for preload destinations that do not support subresource integrity.

MinakoKitani avatar Sep 16 '25 02:09 MinakoKitani

Hey @MinakoKitani

Thanks for reporting this issue. As you have already looked into the potential solution, maybe you would be interested in creating a PR with a fix? :)

Baroshem avatar Sep 16 '25 05:09 Baroshem

Hi @MinakoKitani

The reason for including preload and modulepreload links is documented here: https://github.com/Baroshem/nuxt-security/blob/main/src/runtime/nitro/plugins/30-cspSsgHashes.ts#L75 We tried to implement the RFC as correctly as possible, but there might be some glitches.

I'm not 100% sure what the Chromium discussion list was exactly trying to fix.

In your case, I can see that:

  • the modulepreload links were correctly verified and passed the integrity check
  • the preload on the json link generated a simple warning, informing you that verification was ignored because JSON is a destination that Chromium currently does not support

What is the exact issue you encountered? Did it block your application from running properly?

vejja avatar Sep 16 '25 07:09 vejja