Hash 256 for _header files

Hi there,

To make the management of CSP easier while working with hugo how can i add the hash in csp taken from script tag

# partials/footer.html
<script> some code here</script>

# the above code minified by hugo like this
<script>somecodehere</script>

# layouts/_default/_headers
Content-Security-Policy: script-src 'sha256-somethingsomethin'

how can i make use of the hash to match the exported code in _headers file?

thanks


i try to minify some scripts in advance but hugo still manage to change somethings which result in the end code not matching exactly which fails the hash check by CSP

1 Like

Anyone, who can suggest how to generate sha hash to target the hugo exported script files and make use in CSP.

thanks

Well I guess you could wrap the logic behind your asset processing in a partialCached which returns the resource.

{{/* func/GetScriptAsset */}}
{{ $asset := dict }}
{{ with resources.Get "js/index.js" }}
	{{ $asset = . | js.Build | fingerprint }}
{{ end }}

{{ return $asset }}

then in your head.html:

{{ with partialCached "func/GetScriptAsset" "GetScriptAsset" }}
<script type="text/javascript" integrity="{{ .Data.Integrity }}" crossorigin="anonymous" async="" src="{{ .RelPermalink }}"></script>
{{ end }}

And in your _header output:

{{ with partialCached "func/GetScriptAsset" "GetScriptAsset" }}
Content-Security-Policy: script-src '{{ .Data.Integrity }}'
{{ end }}

This way you can safely retrieve the hash in different places without processing the asset more than once.

1 Like

thanks @regis

i used the code from this page

{{ $js := resources.Get "js/global.js" }}
{{ $secureJS := $js | resources.Fingerprint "sha512" }}
<script type="text/javascript" src="{{ $secureJS.Permalink }}" integrity="{{ $secureJS.Data.Integrity }}"></script>

what is the purpose of the use of partialCached & js.build?

is this an issue that the CI is set to run the build command hugo --gc --minify or the fact that the config.yaml file have minify set to true

minify:
  minifyOutput: true

As something is dones and the generated hash doesn not validate. Do you know if hugo build the hash before minification or after it buuild and minify the js file?

Thanks

js.Build is is only used if you need to process your js (transpile, treeshake etc…) so not always as suppose but often for me.

partialCached makes sure the processing only happen once even though you will need to retrieve the asset twice (once in your HTML, and once in your _headers file.

But without any transformation, it has less value.

1 Like

Thanks @regis

This really helped solve the issue, hugo does have an _header file which can be used while using hugo server is it possible to use the hugo partials in the server.yaml file and export it as the _headers file?

Since all the setup is already done in the server.yaml file. for netlify there seems to be an easy management of _headers but other hosts like cloudflare need an _headers file to read and apply rules.

how are you managin this with Hugo?

thanks again for taking the time and help

Well… I usually generate _headers and _redirects files using Hugo’s output formats but I read my own settings in site.Params.

Now your suggestion would be great, as those could be set for local and deploy… But… I don’t know of a way to retrieve the server config with Hugo… site.Config is very limited and does not return the server config.

1 Like

Hi @regis

thanks for sharing your methods, how can one use the output format _header. do you use an html template as in the _headers file format i cannot really use hugo shortcodes or partials.

is there any theme you know of currently making use of this?

thanks

I’ve written this module which achieves exactly that: GitHub - theNewDynamic/hugo-module-tnd-headers: A Hugo Module for headers

1 Like

Otherwise you would have to add a special output format and media type to your config and assign the created output format to the homepage::

# config.yaml
mediaTypes:
  text/headers_file:
    delimiter: ''
    suffixes:
      - ''

outputFormats:
  headers_file:
    baseName: _headers
    isPlainText: true
    mediatype: text/headers_file
    notAlternative: true

outputs:
  homepage: 
    - HTML
    - headers_file

Then add a layouts/index.headers_file to your layouts directory (targeting the homepage and use Go Template in there to generate what you need.

1 Like

Not exactly related to the thread (and if someone finds this thread in the future) … just a heads-up if you plan on extending support to Cloudflare Pages, their _header file has a limitation on the number of characters per line.

So for CSP, where hashes are usually included, it will eventually reach that limit and the CSP line will be ignored. The only way around it is to use Cloudflare Workers where there is no limit.

That said … back to regular topic. :slight_smile:

hi @techmagus

not exactly sure who you are and why you jump in this conversation. but if you be kind enough to read the issue there are few things i asked.

  • management of CSP while working with hugo
  • how to generate sha hash to target the hugo exported script files
  • if hugo build the hash before minification or after it buuild and minify the js file
  • use the hugo partials in the server.yaml file and export it as the _headers file

Now you seems to have skiped all the hugo related issues and claim it is not hugo related issue.

the limit is 2000 which more than enough to host a long policy.

Anyways as i already know hugo issues are thrown away by claims that issues are not related to hugo even when they are anyways thanks for jumping in.

I agree… this thread is Hugo-related… it’s how to auto-generate CSP headers for inline javascript code. Right now, I need to manually copy/paste the hash into the CSP header each time the script changes or the JS minifier used by Hugo changes the minification algorithm behind the scenes. Being able to auto-generate those headers using Hugo will be tremendously helpful!


I don’t know who marked the solution. But I wouldn’t call that a solution. I was following this thread hoping that it concludes with a link to a Hugo component repo that I can mount as a module in my site and automatically start getting the CSP headers updated :slight_smile:.

1 Like

Hi @kaushalmodi

Regis did provide a really good workaround, so I marked it as a solution. The marking solution was an act of disappointment as, normally, when Hugo managers mark a post not related to Hugo, it is almost impossible to get them onboard or convince.

I wonder as I can use CSP when running hugo server why that policy cannot be simply copied when running hugo? Also, I wonder if there was a method to use hugo partials as suggested by @regis previously

Thanks

I think I need to create a custom solution where I can append the hashes in this fashion (also I am using netlify.toml instead of _header:

(incomplete snippet)

[headers.values]
    Content-Security-Policy = """
      default-src 'none'
      ; script-src 'self'
                   'sha256-fMDMShbcBU8ebA441WwwSx7YSGFgKETas4giHTdT60Y='
                   'sha256-49LG50LG0C5Jy3B/IPFofyWBXgfSNmKf7biDxGiXhbs='
                   'sha256-Zgc2pp+yOmAVogxvTHYBMFKubY0HKk2a0+0+8sX17WY='
                   'sha256-kNsowQfHpWMrbQG7AtSzSuMQg2t/YKwmDWdqeKfm4BI='
                   'sha256-afSIEhWGAPlY458Q4YkhPLVnsVEBh/u5YNlpg6od8TU='
                   'sha256-wFmBttOvPvtTo5Dz9baqkFwDhIwWdpS2ap0mauKBz40='

Reference

1 Like

Hi @kaushalmodi

what i am currently doing is after each build i will look in the code to find the hash and then edit the _header file manually but this need to be done after each build. I cannot use hugo partial in _header file, so i am thinking may be create an extra html file with all the hashes using partial and then simply copy all hashes at once to _header file.

But that also make things complicated as to make sure the extra page doesnt show up in sitemap etc.

So this comment could not help you?

I just need to put in time to develop a custom output format for netlify.toml and corresponding layout that updates only the hashes. I haven’t found time for that. If I get to implementing this, I will share that solution.

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