Incorrect SHA256 value for integrity attribute with fingerprint function: "failed to find a valid digest"

I use Hugo’s fingerprint pipe feature for all the local javascript files my website uses paired with the integrity="" attribute in each <script> tag. Everything worked perfectly until now; my browser stopped using my script files because of this error message in the console:

Failed to find a valid digest in the 'integrity' attribute for resource 'https://mysite.net/js/main.min.0e62b29cf0b0474b2ef7d54a5e40d662cc965393488fe25a78a61a2415bacf29.js' with computed SHA-256 integrity 'P7rRdXhSovg+7BMEijv7+S50RoOSKrKSSI5Vk8X90Qg='. The resource has been blocked.

I tried changing the way fingerprint is applied to the file because of this post and tried with “sha256”, and “sha512”, putting this for every local script tag:

{{ $mainScript := resources.Get "js/main.js" | minify -}}
{{ $secureMainScript := $mainScript | resources.Fingerprint "sha512" }}
<script src="{{ $secureMainScript.Permalink }}" {{ printf "integrity=%q" $secureMainScript.Data.Integrity | safeHTMLAttr }}></script>

However after building (with --ignoreCache) these are the values entered in each public/ file:
<script src=https://xxlsteve.net/js/main.min.59c3ac7087aaeee4bbd948842f4f4a89bc99ac74186ad2f0ce4a1ce1b34eb91c4f3d9a9712872d5c05994083b643b04ef11a4bee521c233e0727337d1ea92641.js integrity="sha512-WcOscIeq7uS72UiEL09KibyZrHQYatLwzkoc4bNOuRxPPZqXEoctXAWZQIO2Q7BO8RpL7lIcIz4HJzN9HqkmQQ==">

And with sha256:

<script src=https://xxlsteve.net/js/main.min.0e62b29cf0b0474b2ef7d54a5e40d662cc965393488fe25a78a61a2415bacf29.js integrity="sha256-DmKynPCwR0su99VKXkDWYsyWU5NIj+JaeKYaJBW6zyk=">

The sequence in the name of the file is the correct SHA string, however the one in integrity="..." is completely different, and not even the same length. What does it correspond to?

In the meanwhile, I replaced every integrity attribute with integrity="" but I’d like to use the feature…

Commit of the repository before the temporary solution (Github)

hugo env
hugo env
hugo v0.111.3-5d4eb5154e1fed125ca8e9b5a0315c4180dab192+extended windows/amd64 BuildDate=2023-03-12T11:40:50Z VendorInfo=gohugoio
GOOS="windows"
GOARCH="amd64"
GOVERSION="go1.20.1"
github.com/sass/libsass="3.6.5"
github.com/webmproject/libwebp="v1.2.4"

I just cloned your repo and replaced the 3rd line shown above, with the following:

<script src="{{ $secureMainScript.Permalink }}" integrity="{{ $secureMainScript.Data.Integrity | safeHTMLAttr }}"></script>

I didn’t encounter any error.

@XXL_Steve You can tighten up your code with:

{{ with resources.Get "js/main.js" | minify | fingerprint "sha512" }}
  <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}"></script>
{{ end }}

There is no need to pass the integrity key/value pair through safeHTMLAttr.

@Sid To tell Go’s html/template package that an attribute key/value pair is safe, you need to pass the key/value pair (not just the value) through safeHTMLAttr. The construct for that is:

<element {{ printf "key=%q" $value | safeHTMLAttr }}>
1 Like

Thanks for the correction @jmooring .

@XXL_Steve, one tip to save some computational resource:

In non-production environments, it’s likely that you don’t need to fingerprint assets (JS, CSS). To build upon Joe’s solution, you can use something like this:

{{ if hugo.IsProduction }}
  {{ $mainScript :=  resources.Get "js/main.js" | minify | fingerprint "sha512" }}
    <script src="{{ $mainScript.RelPermalink }}" integrity="{{ $mainScript.Data.Integrity }}"></script>
{{ else }}
  {{ $mainScript :=  resources.Get "js/main.js" | minify }}
    <script src="{{ $mainScript.RelPermalink }}"></script>
{{ end}}

I tested it once again with @Sid code, and the same problem.
The hash generated in the file name is correct, but the one in the integrity attribute isn’t.

Ex: generated file is main.min.c457f7032d0a853e494b13a51819cd0e7bcfa800d877af5e14a6a24c10aa0b5fa36dbbea4927817edbf6a8f02230408e5dd2843edc9f3e16470235e610f8e949.css but in HTML it’s integrity="sha512-xFf3Ay0KhT5JSxOlGBnNDnvPqADYd69eFKaiTBCqC1+jbbvqSSeBftv2qPAiMECOXdKEPtyfPhZHAjXmEPjpSQ=="

Just a quick FYI… you will need to add this to your site configuration for v0.114.0:

security:
  gotemplates:
    allowActionJSTmpl: true

See https://github.com/gohugoio/hugo/pull/11114

I believe the issue is that printed string for the integrity attribute is the wrong format. And I don’t why, and how to fix it. Because the file name is the correct sha512 string but the attribute is not even the same length of characters

The integrity attribute is the SHAxxx hash, in binary form, encoded to base64. The MDN documentation provides two methods to calculated the integrity attribute:

cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A

shasum -b -a 384 FILENAME.js | awk '{ print $1 }' | xxd -r -p | base64

Note that both methods output/convert the hash to binary before base64 encoding.

You might try this Chrome browser extension, and compare the output to what you generate with Hugo.

When I build your site at 117bd75, all of the integrity attributes are correct.

After further testing I came to the conclusion that integrity doesn’t work for javascript files. They work for stylesheets however. Thanks for helping!

That is false.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.