A plugin for jekyll to calculate Subresource Integrity (SRI) hashes for CSS (even SCSS and SASS) and JS files during build time.
Subresource Integrity (SRI) is a security feature that enables browsers to verify that resources they fetch (for example, from a CDN) are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched resource must match.
from Mozilla docs
Add this section to your application's Gemfile
inside the jekyll_plugins
and execute bundle install
group :jekyll_plugins do
gem 'jekyll-kw-sri'
end
Or install the dependency with bundle
itself, you can use the option --skip-install
, when bundle install
will be called later
bundle add jekyll-kw-sri --group jekyll_plugins
Then add the following to your site's _config.yml
to activate the plugin, see also the Configuration section to change the default configuration.
plugins:
- jekyll-kw-sri
The Plug-In is tested with jekyll 3.8, 3.9, 4.0 and 4.1!
Use the Jekyll Includes kw-integrity-css.html
for css, scss and sass; and the kw-integrity-js.html
for js.
For static, non-rendered
css
files the hash values have to me calculated and stored in a file. SeeAction Items / Shell commands
section about SRI! All the hash-files should be stored in./_includes/integrity
so they can easy used.
The markdown syntax shows the include file with one paramter "the filename".
{% include kw-integrity-css.html file='style.scss' %}
The rendered html will use the default path, the css file and the calculated hash.
<link rel="stylesheet" href="/assets/css/style.css" integrity="sha384-cl6CK1yzEvoM3Sw3dL8YAm/P2VpQiD+mAFVkkb6Bh+23PP1ow2gXXGw4WnQlzO0B" crossorigin="anonymous">
The markdown syntax shows the include file with all paramters. All parameter can be omit. The default values are file = "main.scss", path = "assets/css/" and hash = "sha384".
{% include kw-integrity-css.html file='style.scss' path='my/folder/to/css/' hash='sha512' %}
Use the custom tag sri_scss_hash {% raw %}{% sri_scss_hash style.css %}
{% endraw %}.
This approach was inspired by vcsjones.dev Blog and vcsjones.dev GitHub.
The html
inside the post or page markdown file, shows a usage of a scss
file which will be compiled to a css
. The hash of the integrity will be generated during the build time.
<link rel="stylesheet" href="{{ '/assets/css/kargware.css' | relative_url }}" integrity="{% sri_scss_hash /assets/css/kargware.scss %}" crossorigin="anonymous">
The result of the html inside the markdown is the href
and the integrity
.
<link rel="stylesheet" href="/assets/css/kargware.css" integrity="sha384-cl6CK1yzEvoM3Sw3dL8YAm/P2VpQiD+mAFVkkb6Bh+23PP1ow2gXXGw4WnQlzO0B" crossorigin="anonymous">
- 0.1.0 Add html include files to use them with
{% include kw-integrity-css.html %}
or{% include kw-integrity-js.html %}
- 0.0.x Add the custom tag
{% sri_scss_hash %}
Add kw-sri
section to _config.yml
configure the plugin globally. If you want to use defauls you can ommit the config-section.
kw-sri:
createTmpfile: false
hash_type: 'sha384'
write_source_mapping_url: true
Configuration values
Key | Description | Values (default) |
---|---|---|
createTmpfile | Debug-Only, save the rendered sass or scss as css | false, true |
hash_type | Which kind of integrity hash | sha256, sha384, sha512 |
write_source_mapping_url | Add the map-file like to the css | false, true |
Run linting and tests
bundle exec rubocop
bundle exec rake test
Build gem package
bundle exec rake build
Publish gem package
bundle exec rake release
Calc a SRI Integrity hash of ./style.css
in format sha256
openssl dgst -sha256 -binary ./style.css | openssl base64 -A
Calc different SRI integrity hash-files from css-files
(same is valid for js-files
) in format sha256
, sha384
and sha512
inside a Makefile
calc-integrity-files:
for strength in 256 384 512 ; do \
cat ./assets/css/style.min.css | openssl dgst -sha$$strength -binary | openssl base64 -A > ./_includes/integrity/style.min.css.sha$$strength ; \
cat ./assets/css/main.css | openssl dgst -sha$$strength -binary | openssl base64 -A > ./_includes/integrity/main.css.sha$$strength ; \
cat ./assets/js/script.js | openssl dgst -sha$$strength -binary | openssl base64 -A > ./_includes/integrity/script.js.sha$$strength ; \
done
- Create a
Appraisals
file - Generate
Gemfiles
bundle exec appraisal generate
Inside the render(context)
function of a Liquid::Tag
there is a context object. With that context you can get the site
object, anyhow when you want to cretae your temporry site and context you need a workaround.
Normal way to get the site object from the render function of a custom tag
site = context.registers[:site]
Create a temporary site and context of a jekyll environment
site = Jekyll::Site.new(Jekyll::Configuration::DEFAULTS)
context = Liquid::Context.new({}, {}, { site: site })
Use Jekyll::Tags::IncludeRelativeTag
instead of Liquid::Tag
as base class of the custom jekyll tag SriScssHashTag
will help to read the content of the scss or sass files.
Sometimes, especially during testing, the site object is not perfectly setup. So the function find_converter_instance
will throw an error.
Default implementation to find the converter.
converter = site.find_converter_instance(Jekyll::Converters::Scss)
Workaround implementation to find the converter.
converter = if defined? site.find_converter_instance
site.find_converter_instance(Jekyll::Converters::Scss)
else
site.getConverterImpl(::Jekyll::Converters::Scss)
end
bundle init
bundle add rake
bundle add simplecov
bundle add minitest
bundle add minitest-reporters
bundle add minitest-profile
bundle add rspec-mocks
bundle add rdiscount
bundle add redcarpet
bundle add shoulda