I began adding subresource integrity and ran into an issue. The sample found in
the documentation does not produce a valid subresource integrity hash:
<script src="{{ get_url(path="js/app.js") }}" integrity="sha384-{{ get_file_hash(path="js/app.js", sha_type=384) }}"></script>
This check is failing as the get_file_hash()
method is returning a hex-encoded
version of the digest instead of a base64 encoded version as defined in the
official spec and MDN.
I haven’t contributed to Zola before, but happy to open a PR with a fix and
update the documentation. The way I see it there are a couple of different
paths to getting to a point where valid integrity hashes could be generated.
The most flexible would likely to be to add two more built-in filters
hex_encode
and hex_decode
to match the existing base64_encode
and
base64_decode
. This doesn’t change any existing usage, and is potentially
useful for other things. An updated integrity attribute can be generated like
this:
<script src="{{ get_url(path="js/app.js") }}" integrity="sha384-{{ get_file_hash(path="js/app.js", sha_type=384) | hex_decode | base64_encode }}"></script>
Not very ergonomic but it does work. The next reasonable option would be to add
another optional argument to the existing get_file_hash()
method such as
encoding
allowing you to specify a base64 encoding instead of a hex decoding.
The resulting usage would look something like the following:
<script src="{{ get_url(path="js/app.js") }}" integrity="sha384-{{ get_file_hash(path="js/app.js", sha_type=384, encoding=base64) }}"></script>
This seems like a relatively small change and shouldn’t have any impact on any
existing usage as long as encoding defaults to hex
. The last idea is the most
ergonomic from a user’s perspective, use a dedicated helper for generating the
integrity string. I suspect this falls foul of keeping the feature set minimal,
but wanted to include it as an option anyway. Effectively this would behave the
same way as the existing get_file_hash
but properly format the result
specifically for an integrity attribute:
<script src="{{ get_url(path="js/app.js") }}" integrity="{{ get_file_integrity(path="js/app.js", sha_type=384) }}"></script>
All of those options seem like they would be quite quick to implement, and easy
enough to update the documentation at the same time. What direction seems most
appropriate?