Skip to content

Commit

Permalink
Add subresource integrity for JS and CSS assets (mastodon#15096)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gargron authored and umonaca committed Nov 8, 2020
1 parent 1886fc4 commit ad4c5af
Show file tree
Hide file tree
Showing 31 changed files with 79 additions and 39 deletions.
2 changes: 1 addition & 1 deletion app/views/about/more.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= site_hostname

- content_for :header_tags do
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'public', crossorigin: 'anonymous'
= render partial: 'shared/og'
%meta{ name: 'robots', content: 'noindex' }/

Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/action_logs/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= t('admin.action_logs.title')

- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

= form_tag admin_action_logs_url, method: 'GET', class: 'simple_form' do
= hidden_field_tag :target_account_id, params[:target_account_id] if params[:target_account_id].present?
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/custom_emojis/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= t('admin.custom_emojis.title')

- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

- if can?(:create, :custom_emoji)
- content_for :heading_actions do
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/domain_allows/new.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

- content_for :page_title do
= t('admin.domain_allows.add_new')
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/domain_blocks/edit.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

- content_for :page_title do
= t('admin.domain_blocks.edit')
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/domain_blocks/new.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

- content_for :page_title do
= t('.title')
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/ip_blocks/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= t('admin.ip_blocks.title')

- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

- if can?(:create, :ip_block)
- content_for :heading_actions do
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/pending_accounts/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= t('admin.pending_accounts.title', count: User.pending.count)

- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

= form_for(@form, url: batch_admin_pending_accounts_path) do |f|
= hidden_field_tag :page, params[:page] || 1
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/reports/show.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

- content_for :page_title do
= t('admin.reports.report', id: @report.id)
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/settings/edit.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

- content_for :page_title do
= t('admin.settings.title')
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/statuses/index.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

- content_for :page_title do
= t('admin.statuses.title')
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/tags/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= t('admin.tags.title')

- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

.filters
.filter-subset
Expand Down
2 changes: 1 addition & 1 deletion app/views/auth/sessions/two_factor.html.haml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('auth.login')

=javascript_pack_tag 'two_factor_authentication', integrity: true, crossorigin: 'anonymous'
=javascript_pack_tag 'two_factor_authentication', crossorigin: 'anonymous'

- if @webauthn_enabled
= render partial: 'auth/sessions/two_factor/webauthn_form', locals: { hidden: @scheme_type != 'webauthn' }
Expand Down
10 changes: 5 additions & 5 deletions app/views/home/index.html.haml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
- content_for :header_tags do
= preload_link_tag asset_pack_path('features/getting_started.js'), crossorigin: 'anonymous'
= preload_link_tag asset_pack_path('features/compose.js'), crossorigin: 'anonymous'
= preload_link_tag asset_pack_path('features/home_timeline.js'), crossorigin: 'anonymous'
= preload_link_tag asset_pack_path('features/notifications.js'), crossorigin: 'anonymous'
= preload_pack_asset 'features/getting_started.js', crossorigin: 'anonymous'
= preload_pack_asset 'features/compose.js', crossorigin: 'anonymous'
= preload_pack_asset 'features/home_timeline.js', crossorigin: 'anonymous'
= preload_pack_asset 'features/notifications.js', crossorigin: 'anonymous'

%meta{name: 'applicationServerKey', content: Rails.configuration.x.vapid_public_key}
= render_initial_state
= javascript_pack_tag 'application', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'application', crossorigin: 'anonymous'

.app-holder#mastodon{ data: { props: Oj.dump(default_props) } }
%noscript
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/admin.html.haml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
- content_for :header_tags do
= render_initial_state
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'public', crossorigin: 'anonymous'

- content_for :content do
.admin-wrapper
Expand Down
8 changes: 4 additions & 4 deletions app/views/layouts/application.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@

%title= content_for?(:page_title) ? safe_join([yield(:page_title).chomp.html_safe, title], ' - ') : title

= stylesheet_pack_tag 'common', media: 'all'
= stylesheet_pack_tag current_theme, media: 'all'
= javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
= stylesheet_pack_tag 'common', media: 'all', crossorigin: 'anonymous'
= stylesheet_pack_tag current_theme, media: 'all', crossorigin: 'anonymous'
= javascript_pack_tag 'common', crossorigin: 'anonymous'
= javascript_pack_tag "locale_#{I18n.locale}", crossorigin: 'anonymous'
= csrf_meta_tags
%meta{ name: 'style-nonce', content: request.content_security_policy_nonce }

Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/auth.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- content_for :header_tags do
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'public', crossorigin: 'anonymous'

- content_for :content do
.container-alt
Expand Down
4 changes: 2 additions & 2 deletions app/views/layouts/embedded.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
- if storage_host?
%link{ rel: 'dns-prefetch', href: storage_host }/

= stylesheet_pack_tag 'common', media: 'all'
= stylesheet_pack_tag Setting.default_settings['theme'], media: 'all'
= stylesheet_pack_tag 'common', media: 'all', crossorigin: 'anonymous'
= stylesheet_pack_tag Setting.default_settings['theme'], media: 'all', crossorigin: 'anonymous'
= javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
= render_initial_state
Expand Down
8 changes: 4 additions & 4 deletions app/views/layouts/error.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
%meta{ charset: 'utf-8' }/
%title= safe_join([yield(:page_title), Setting.default_settings['site_title']], ' - ')
%meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/
= stylesheet_pack_tag 'common', media: 'all'
= stylesheet_pack_tag Setting.default_settings['theme'], media: 'all'
= javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'error', integrity: true, crossorigin: 'anonymous'
= stylesheet_pack_tag 'common', media: 'all', crossorigin: 'anonymous'
= stylesheet_pack_tag Setting.default_settings['theme'], media: 'all', crossorigin: 'anonymous'
= javascript_pack_tag 'common', crossorigin: 'anonymous'
= javascript_pack_tag 'error', crossorigin: 'anonymous'
%body.error
.dialog
.dialog__illustration
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/modal.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- content_for :header_tags do
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'public', crossorigin: 'anonymous'

- content_for :content do
- if user_signed_in? && !@hide_header
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/public.html.haml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
- content_for :header_tags do
= render_initial_state
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'public', crossorigin: 'anonymous'

- content_for :content do
.public-layout
Expand Down
2 changes: 1 addition & 1 deletion app/views/media/player.html.haml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
- content_for :header_tags do
= render_initial_state
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'public', crossorigin: 'anonymous'

- if @media_attachment.video?
= react_component :video, src: @media_attachment.file.url(:original), preview: @media_attachment.thumbnail.present? ? @media_attachment.thumbnail.url : @media_attachment.file.url(:small), blurhash: @media_attachment.blurhash, width: 670, height: 380, editable: true, detailed: true, inline: true, alt: @media_attachment.description do
Expand Down
2 changes: 1 addition & 1 deletion app/views/public_timelines/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

- content_for :header_tags do
%meta{ name: 'robots', content: 'noindex' }/
= javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'about', crossorigin: 'anonymous'

.page-header
%h1= t('about.see_whats_happening')
Expand Down
2 changes: 1 addition & 1 deletion app/views/relationships/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
= t('settings.relationships')

- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'

.filters
.filter-subset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
.actions
= f.button :button, t('webauthn_credentials.add'), class: 'js-webauthn', type: :submit

= javascript_pack_tag 'two_factor_authentication', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'two_factor_authentication', crossorigin: 'anonymous'
2 changes: 1 addition & 1 deletion app/views/shares/show.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- content_for :header_tags do
= render_initial_state
= javascript_pack_tag 'share', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'share', crossorigin: 'anonymous'

#mastodon-compose{ data: { props: Oj.dump(default_props) } }
2 changes: 1 addition & 1 deletion app/views/tags/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
%meta{ name: 'robots', content: 'noindex' }/
%link{ rel: 'alternate', type: 'application/rss+xml', href: tag_url(@tag, format: 'rss') }/

= javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'about', crossorigin: 'anonymous'
= render 'og'

.page-header
Expand Down
2 changes: 2 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
require_relative '../lib/devise/two_factor_ldap_authenticatable'
require_relative '../lib/devise/two_factor_pam_authenticatable'
require_relative '../lib/chewy/strategy/custom_sidekiq'
require_relative '../lib/webpacker/manifest_extensions'
require_relative '../lib/webpacker/helper_extensions'

Dotenv::Railtie.load

Expand Down
3 changes: 2 additions & 1 deletion config/webpack/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ module.exports = {
chunkFilename: 'css/[name]-[contenthash:8].chunk.css',
}),
new AssetsManifestPlugin({
integrity: false,
integrity: true,
integrityHashes: ['sha256'],
entrypoints: true,
writeToDisk: true,
publicPath: true,
Expand Down
20 changes: 20 additions & 0 deletions lib/webpacker/helper_extensions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

module Webpacker::HelperExtensions
def javascript_pack_tag(name, **options)
src, integrity = current_webpacker_instance.manifest.lookup!(name, type: :javascript, with_integrity: true)
javascript_include_tag(src, options.merge(integrity: integrity))
end

def stylesheet_pack_tag(name, **options)
src, integrity = current_webpacker_instance.manifest.lookup!(name, type: :stylesheet, with_integrity: true)
stylesheet_link_tag(src, options.merge(integrity: integrity))
end

def preload_pack_asset(name, **options)
src, integrity = current_webpacker_instance.manifest.lookup!(name, with_integrity: true)
preload_link_tag(src, options.merge(integrity: integrity))
end
end

Webpacker::Helper.prepend(Webpacker::HelperExtensions)
17 changes: 17 additions & 0 deletions lib/webpacker/manifest_extensions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

module Webpacker::ManifestExtensions
def lookup(name, pack_type = {})
asset = super

if pack_type[:with_integrity] && asset.respond_to?(:dig)
[asset.dig('src'), asset.dig('integrity')]
elsif asset.respond_to?(:dig)
asset.dig('src')
else
asset
end
end
end

Webpacker::Manifest.prepend(Webpacker::ManifestExtensions)

0 comments on commit ad4c5af

Please sign in to comment.