Enable Subresource Integrity

This commit is contained in:
Sebastian Serth
2022-09-03 03:22:44 +02:00
parent 51e9daf930
commit 9e08f3a6a8
7 changed files with 93 additions and 7 deletions

View File

@ -8,7 +8,7 @@ module ExerciseHelper
end
def qa_js_tag
javascript_include_tag "#{qa_url}/assets/qa_api.js"
javascript_include_tag "#{qa_url}/assets/qa_api.js", integrity: true, crossorigin: 'anonymous'
end
def qa_url

View File

@ -9,10 +9,10 @@ html lang="#{I18n.locale || I18n.default_locale}"
= favicon_link_tag('/favicon.png', type: 'image/png')
= favicon_link_tag('/favicon.png', rel: 'apple-touch-icon', type: 'image/png')
= action_cable_meta_tag
= stylesheet_pack_tag('application', 'stylesheets', media: 'all', 'data-turbolinks-track': true)
= stylesheet_link_tag('application', media: 'all', 'data-turbolinks-track': true)
= javascript_pack_tag('application', 'data-turbolinks-track': true, defer: false)
= javascript_include_tag('application', 'data-turbolinks-track': true)
= stylesheet_pack_tag('application', 'stylesheets', media: 'all', 'data-turbolinks-track': true, integrity: true, crossorigin: 'anonymous')
= stylesheet_link_tag('application', media: 'all', 'data-turbolinks-track': true, integrity: true, crossorigin: 'anonymous')
= javascript_pack_tag('application', 'data-turbolinks-track': true, defer: false, integrity: true, crossorigin: 'anonymous')
= javascript_include_tag('application', 'data-turbolinks-track': true, integrity: true, crossorigin: 'anonymous')
= yield(:head)
= csrf_meta_tags
= timeago_script_tag nonce: true

View File

@ -1,12 +1,14 @@
// See the shakacode/shakapacker README and docs directory for advice on customizing your webpackConfig.
const { webpackConfig, merge } = require('shakapacker')
const { webpackConfig, config, merge } = require('shakapacker')
const webpack = require('webpack');
const CompressionPlugin = require("compression-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const WebpackAssetsManifest = require('webpack-assets-manifest');
const { SubresourceIntegrityPlugin } = require("webpack-subresource-integrity");
// Custom ERB loader to disable Spring and prevent crashes
const erb = require("./loaders/erb");
@ -30,7 +32,9 @@ const envConfig = module.exports = {
],
},
output: {
publicPath: relative_url_root + public_output_path
publicPath: relative_url_root + public_output_path,
// the following setting is required for SRI to work:
crossOriginLoading: 'anonymous',
},
performance: {
// Turn off size warnings for large assets
@ -53,6 +57,15 @@ const envConfig = module.exports = {
}),
new CompressionPlugin(),
new MiniCssExtractPlugin(),
new SubresourceIntegrityPlugin(),
new WebpackAssetsManifest({
entrypoints: true,
integrity: false,
writeToDisk: true,
entrypointsUseAssets: true,
publicPath: true,
output: config.manifestPath,
})
],
resolve: {
extensions: ['.css', '.ts', '.tsx'],
@ -65,4 +78,8 @@ const envConfig = module.exports = {
stats: 'minimal',
}
// Use the two lines below to remove the original WebpackAssetsManifest and replace it with our custom config.
const filteredPlugins = webpackConfig.plugins.filter((plugin) => !(plugin instanceof WebpackAssetsManifest))
webpackConfig.plugins = filteredPlugins;
module.exports = merge(webpackConfig, envConfig)

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
module Webpacker::SriHelperExtensions
def stylesheet_link_tag(*sources, **options)
tags = sources.map do |stylesheet|
if stylesheet.is_a?(Hash)
super(stylesheet[:src], options.merge(integrity: stylesheet[:integrity]))
else
super(stylesheet, options)
end
end
safe_join(tags)
end
def javascript_include_tag(*sources, **options)
tags = sources.map do |javascript|
if javascript.is_a?(Hash)
super(javascript[:src], options.merge(integrity: javascript[:integrity]))
else
super(javascript, options)
end
end
safe_join(tags)
end
end
Sprockets::Rails::Helper.prepend(Webpacker::SriHelperExtensions)

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
module Webpacker::SriManifestExtensions
def lookup(name, pack_type = {})
asset = super
augment_with_integrity asset, pack_type
end
def lookup_pack_with_chunks(name, pack_type = {})
assets = super
assets.map do |asset|
augment_with_integrity asset, pack_type
end
end
def augment_with_integrity(asset, _pack_type = {})
if asset.respond_to?(:dig) && asset['integrity']
{src: asset['src'], integrity: asset['integrity']}
elsif asset.respond_to?(:dig)
asset['src']
else
asset
end
end
end
Webpacker::Manifest.prepend(Webpacker::SriManifestExtensions)

View File

@ -51,6 +51,7 @@
"webpack-cli": "^4.10.0",
"webpack-merge": "^5.8.0",
"webpack-sources": "^3.2.3",
"webpack-subresource-integrity": "^5.1.0",
"xss": "^1.0.14"
},
"devDependencies": {

View File

@ -4199,6 +4199,11 @@ type-is@~1.6.18:
media-typer "0.3.0"
mime-types "~2.1.24"
typed-assert@^1.0.8:
version "1.0.9"
resolved "https://registry.yarnpkg.com/typed-assert/-/typed-assert-1.0.9.tgz#8af9d4f93432c4970ec717e3006f33f135b06213"
integrity sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==
underscore@^1.13.4:
version "1.13.4"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.4.tgz#7886b46bbdf07f768e0052f1828e1dcab40c0dee"
@ -4387,6 +4392,13 @@ webpack-sources@^3.2.3:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
webpack-subresource-integrity@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz#8b7606b033c6ccac14e684267cb7fb1f5c2a132a"
integrity sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==
dependencies:
typed-assert "^1.0.8"
webpack@^5.74.0:
version "5.74.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980"