publify_core 9.2.1 → 9.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of publify_core might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b54212d5fc4e4291890a1aa527561a41dc19ad64d58841c0407e14f9e6ccebc
4
- data.tar.gz: 7ebc8493ba977031d7ebcb3ac4a659fcf248d419a97ee09418a618eb29cee2dc
3
+ metadata.gz: 8598a2b44749716a7bf3f75ab494ff6ba4ef327f29d6606ed3fd21ccce7df918
4
+ data.tar.gz: b3f58570a4180cb07bfa2852d3bf0c10160feb9f14039875d6e5182fbb56a368
5
5
  SHA512:
6
- metadata.gz: 8a16d3eeec887dec33e6733d7eab215f1677e808dcecde23ab7b4a8c8b65df748a71bdfe74312e491c48183b18ea0814aa859ca4ba3971303f652ef5adca9846
7
- data.tar.gz: 53d08aac3318179a27a067755546f88b80fc24555fcff1d4d4c76aad7b2b4284d2dad3cb246858e929781bce8fee1c608b922d8f2c017b1c7729c0d547bfe912
6
+ metadata.gz: 5ceafbc0b711d3c0d113e61e9339c9175b6cf18afb08fded9321148d2b3b7ddf1809a9de8de0428f5364820d15de19a58a4b0a811018e6cc210357ccb49e868f
7
+ data.tar.gz: 7e476032ad37744aee63a7f746c81f020684857fedd43ff6468648ce1133280fd3efc7b78bea560ffd69d34b250dc120e05c767a44361eb376d91de54ecd2c35
data/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## 9.2.5 / 2021-10-11
4
+
5
+ This release fixes several security issues:
6
+
7
+ * Block ability to switch themes using a GET request; use a POST instead
8
+ * Disallow user self-registration rather than hiding it
9
+ * Let the browser not cache admin pages
10
+ * Limit the set of allowed mime types for uploaded media
11
+ * Limit allowed HTML in articles, pages and notes
12
+
13
+ Additionally, it includes the following changes:
14
+
15
+ * Fix resource size display in admin resource list
16
+ * Trigger download of media in the Media Library in admin instead of displaying
17
+ them directly
18
+
19
+ ## 9.2.4 / 2021-10-02
20
+
21
+ * Explicitly require at least version 1.12.5 of nokogiri to avoid a security issue
22
+ * Drop support for Ruby 2.4 since it is incompatible with nokogiri 1.12.5
23
+
24
+ ## 9.2.3 / 2021-05-22
25
+
26
+ * Bump Rails dependency to 5.2.6
27
+ * Replace mimemagic with marcel
28
+
29
+ ## 9.2.2 / 2021-03-21
30
+
31
+ * No changes
32
+
3
33
  ## 9.2.1 / 2021-03-20
4
34
 
5
35
  * No changes
@@ -10,6 +10,7 @@ class Admin::BaseController < BaseController
10
10
  layout "administration"
11
11
 
12
12
  before_action :login_required, except: [:login, :signup]
13
+ before_action :no_caching
13
14
 
14
15
  private
15
16
 
@@ -24,4 +25,9 @@ class Admin::BaseController < BaseController
24
25
  name: controller_name.humanize)
25
26
  redirect_to action: "index"
26
27
  end
28
+
29
+ def no_caching
30
+ response.cache_control[:extras] =
31
+ ["no-cache", "max-age=0", "must-revalidate", "no-store"]
32
+ end
27
33
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Users::RegistrationsController < Devise::RegistrationsController
4
+ include BlogHelper
5
+ before_action :require_signup_allowed
6
+
7
+ private
8
+
9
+ def require_signup_allowed
10
+ render plain: "Not found", status: :not_found unless this_blog.allow_signup?
11
+ end
12
+ end
@@ -240,10 +240,15 @@ module BaseHelper
240
240
  end
241
241
 
242
242
  def nofollowify_links(string)
243
+ raise ArgumentError, "string", "must be html_safe" unless string.html_safe?
244
+
243
245
  if this_blog.dofollowify
244
246
  string
245
247
  else
246
- string.gsub(/<a(.*?)>/i, '<a\1 rel="nofollow">')
248
+ followify_scrubber = Loofah::Scrubber.new do |node|
249
+ node.set_attribute "rel", "nofollow" if node.name == "a"
250
+ end
251
+ sanitize h(string), scrubber: followify_scrubber
247
252
  end
248
253
  end
249
254
 
@@ -225,10 +225,6 @@ class Article < Content
225
225
  published_at.to_i > blog.sp_article_auto_close.days.ago.to_i
226
226
  end
227
227
 
228
- def content_fields
229
- [:body, :extended]
230
- end
231
-
232
228
  # The web interface no longer distinguishes between separate "body" and
233
229
  # "extended" fields, and instead edits everything in a single edit field,
234
230
  # separating the extended content using "\<!--more-->".
@@ -50,8 +50,4 @@ class Comment < Feedback
50
50
  def originator
51
51
  author
52
52
  end
53
-
54
- def content_fields
55
- [:body]
56
- end
57
53
  end
@@ -5,6 +5,12 @@ module ContentBase
5
5
  base.extend ClassMethods
6
6
  end
7
7
 
8
+ class ContentTextHelpers
9
+ include ActionView::Helpers::UrlHelper
10
+ include ActionView::Helpers::TextHelper
11
+ include ActionView::Helpers::SanitizeHelper
12
+ end
13
+
8
14
  attr_accessor :just_changed_published_status
9
15
  alias just_changed_published_status? just_changed_published_status
10
16
 
@@ -26,7 +32,7 @@ module ContentBase
26
32
  elsif html_map(field)
27
33
  generate_html(field)
28
34
  else
29
- raise "Unknown field: #{field.inspect} in content.html"
35
+ raise ArgumentError, "Field #{field.inspect} is not valid for #{self.class}"
30
36
  end
31
37
  end
32
38
 
@@ -39,10 +45,10 @@ module ContentBase
39
45
  html_postprocess(field, html).to_s
40
46
  end
41
47
 
42
- # Post-process the HTML. This is a noop by default, but Comment overrides it
43
- # to enforce HTML sanity.
48
+ # Post-process the HTML
44
49
  def html_postprocess(_field, html)
45
- html
50
+ helper = ContentTextHelpers.new
51
+ helper.sanitize html
46
52
  end
47
53
 
48
54
  def html_preprocess(_field, html)
@@ -11,12 +11,6 @@ class Feedback < ApplicationRecord
11
11
  include PublifyGuid
12
12
  include ContentBase
13
13
 
14
- class ContentTextHelpers
15
- include ActionView::Helpers::UrlHelper
16
- include ActionView::Helpers::TextHelper
17
- include ActionView::Helpers::SanitizeHelper
18
- end
19
-
20
14
  validate :feedback_not_closed, on: :create
21
15
  validates :article, presence: true
22
16
 
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "mimemagic"
3
+ require "marcel"
4
4
 
5
5
  class ResourceUploader < CarrierWave::Uploader::Base
6
6
  include CarrierWave::MiniMagick
7
7
  before :cache, :check_image_content_type!
8
8
 
9
+ def content_type_allowlist
10
+ [%r{image/}, %r{audio/}, %r{video/}, "text/plain"]
11
+ end
12
+
9
13
  def store_dir
10
14
  "files/#{model.class.to_s.underscore}/#{model.id}"
11
15
  end
@@ -50,14 +54,9 @@ class ResourceUploader < CarrierWave::Uploader::Base
50
54
  content_type = nil
51
55
 
52
56
  File.open(new_file.path) do |fd|
53
- content_type = MimeMagic.by_magic(fd).try(:type)
57
+ content_type = Marcel::MimeType.for(fd)
54
58
  end
55
59
 
56
60
  content_type
57
61
  end
58
-
59
- # NOTE: This method was copied from MagicMimeBlacklist from CarrierWave 1.0.0.
60
- def filemagic
61
- @filemagic ||= FileMagic.new(FileMagic::MAGIC_MIME_TYPE)
62
- end
63
62
  end
@@ -33,38 +33,34 @@
33
33
  </tr>
34
34
  <% end %>
35
35
 
36
- <% for upload in @resources %>
36
+ <% for resource in @resources %>
37
37
  <tr>
38
38
  <td>
39
- <% if upload.mime =~ /image/ %>
40
- <a href="<%= upload.upload.medium.url %>" data-toggle="lightbox">
41
- <%= image_tag(upload.upload.thumb.url) %>
42
- </a>
39
+ <% if resource.mime =~ /image/ %>
40
+ <a href="<%= resource.upload.medium.url %>" data-toggle="lightbox">
41
+ <%= image_tag(resource.upload.thumb.url) %>
42
+ </a>
43
43
  <% else %>
44
- <%= link_to(upload.upload_url, upload.upload_url) %>
44
+ <%= link_to(resource.upload_url, resource.upload_url, download: resource.upload.identifier) %>
45
45
  <% end %>
46
46
  <p>
47
47
  <small>
48
- <% if upload.mime =~ /image/ %>
49
- <%= link_to(t('.thumbnail'), upload.upload.thumb.url) %> |
50
- <%= link_to(t('.medium_size'), upload.upload.medium.url) %> |
51
- <%= link_to(t('.original_size'), upload.upload.url) %> |
48
+ <% if resource.mime =~ /image/ %>
49
+ <%= link_to(t('.thumbnail'), resource.upload.thumb.url) %> |
50
+ <%= link_to(t('.medium_size'), resource.upload.medium.url) %> |
51
+ <%= link_to(t('.original_size'), resource.upload.url) %> |
52
52
  <% end %>
53
53
  <%= link_to(t('.delete'),
54
- { action: 'destroy', id: upload.id, search: params[:search], page: params[:page] },
54
+ { action: 'destroy', id: resource.id, search: params[:search], page: params[:page] },
55
55
  { confirm: t('.are_you_sure'), method: :delete }) %>
56
56
  </small>
57
57
  </p>
58
58
  </td>
59
59
  <td>
60
- <%= upload.mime %>
60
+ <%= resource.mime %>
61
61
  </td>
62
- <td><%= begin
63
- h upload.size
64
- rescue StandardError
65
- 0
66
- end %> bytes</td>
67
- <td><%= l(upload.created_at, format: :short) %></td>
62
+ <td><%= resource.upload.size %> bytes</td>
63
+ <td><%= l(resource.created_at, format: :short) %></td>
68
64
  </tr>
69
65
  <% end %>
70
66
  <%= display_pagination(@resources, 6) %>
@@ -16,10 +16,10 @@
16
16
  </div>
17
17
  <% else %>
18
18
  <div>
19
- <h3><%= link_to(theme.name, switch_url, title: t('.use_this_theme')) %></h3>
20
- <%= link_to(image_tag(preview_url, class: 'img-thumbnail'), switch_url, title: t('.use_this_theme')) %>
19
+ <h3><%= theme.name %></h3>
20
+ <%= image_tag(preview_url, class: 'img-thumbnail') %>
21
21
  <%= raw theme.description_html %>
22
- <p><%= link_to(t('.use_this_theme'), switch_url, class: 'btn btn-info') %></p>
22
+ <p><%= button_to(t('.use_this_theme'), switch_url, class: 'btn btn-info') %></p>
23
23
  </div>
24
24
  <% end %>
25
25
  </div>
@@ -5,7 +5,7 @@
5
5
  <p><%= link_to_permalink article, t('.continue_reading') %></p>
6
6
  </div>
7
7
  <% else %>
8
- <%= raw article.html(:body) %>
8
+ <%= article.html(:body) %>
9
9
  <% if article.extended? %>
10
10
  <div class="extended">
11
11
  <p><%= link_to_permalink article, t('.continue_reading') %></p>
@@ -1,4 +1,4 @@
1
1
  <% cache article do %>
2
- <%= raw article.html(:body) %>
3
- <%= raw article.html(:extended) %>
2
+ <%= article.html(:body) %>
3
+ <%= article.html(:extended) %>
4
4
  <% end %>
@@ -1,3 +1,3 @@
1
1
  <div id="viewpage">
2
- <%= raw html @page %>
2
+ <%= html @page %>
3
3
  </div>
@@ -6,7 +6,7 @@
6
6
  <%= t('.said') %> <%= display_date_and_time comment.created_at %>:
7
7
  </p>
8
8
  <div class="content">
9
- <%= raw nofollowify_links comment.generate_html(:body) %>
9
+ <%= nofollowify_links comment.generate_html(:body) %>
10
10
  <% unless comment.published? %>
11
11
  <div class="spamwarning">
12
12
  <%= t('.this_comment_has_been_flagged_for_moderator_approval') %>
@@ -1,7 +1,7 @@
1
1
  <% cache [note, note.user] do %>
2
2
  <article class='status'>
3
3
  <%= author_picture note %>
4
- <div class='p-name entry-title e-content entry-content article'><%= raw note.html(:body) %></div>
4
+ <div class='p-name entry-title e-content entry-content article'><%= note.html(:body) %></div>
5
5
  <footer>
6
6
  <small>
7
7
  <%= link_to_permalink(note, display_date_and_time(note.published_at)) %> |
@@ -2,7 +2,7 @@
2
2
  <% for note in @notes %>
3
3
  <div class='h-entry hentry h-as-note'>
4
4
  <article>
5
- <p class='p-name entry-title e-content entry-content article'><%= raw note.html(:body) %></p>
5
+ <p class='p-name entry-title e-content entry-content article'><%= note.html(:body) %></p>
6
6
  <footer>
7
7
  <small><%= link_to_permalink(note, display_date_and_time(note.published_at)) %></small>
8
8
  </footer>
data/config/routes.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Rails.application.routes.draw do
4
- devise_for :users
4
+ devise_for :users, controllers: { registrations: "users/registrations" }
5
+
5
6
  # TODO: use only in archive sidebar. See how made other system
6
7
  get ":year/:month", to: "articles#index", year: /\d{4}/, month: /\d{1,2}/,
7
8
  as: "articles_by_month", format: false
@@ -144,7 +145,7 @@ Rails.application.routes.draw do
144
145
  resources :themes, only: [:index], format: false do
145
146
  collection do
146
147
  get "preview"
147
- get "switchto"
148
+ post "switchto"
148
149
  end
149
150
  end
150
151
 
@@ -0,0 +1,5 @@
1
+ <html>
2
+ <body>
3
+ <p>Hello!</p>
4
+ </body>
5
+ </html>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PublifyCore
4
- VERSION = "9.2.1"
4
+ VERSION = "9.2.5"
5
5
  end
@@ -82,16 +82,14 @@ class SpamProtection
82
82
  def query_rbls(rbls, *subdomains)
83
83
  rbls.each do |rbl|
84
84
  subdomains.uniq.each do |d|
85
- begin
86
- response = IPSocket.getaddress([d, rbl].join("."))
87
- if response.start_with?("127.0.0.")
88
- throw :hit,
89
- "#{rbl} positively resolved subdomain #{d} => #{response}"
90
- end
91
- rescue SocketError
92
- # NXDOMAIN response => negative: d is not in RBL
93
- next
85
+ response = IPSocket.getaddress([d, rbl].join("."))
86
+ if response.start_with?("127.0.0.")
87
+ throw :hit,
88
+ "#{rbl} positively resolved subdomain #{d} => #{response}"
94
89
  end
90
+ rescue SocketError
91
+ # NXDOMAIN response => negative: d is not in RBL
92
+ next
95
93
  end
96
94
  end
97
95
  false
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: publify_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.2.1
4
+ version: 9.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matijs van Zuijlen
8
8
  - Yannick François
9
9
  - Thomas Lecavellier
10
10
  - Frédéric de Villamil
11
- autorequire:
11
+ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2021-03-20 00:00:00.000000000 Z
14
+ date: 2021-10-11 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: aasm
@@ -202,39 +202,39 @@ dependencies:
202
202
  - !ruby/object:Gem::Version
203
203
  version: 1.2.1
204
204
  - !ruby/object:Gem::Dependency
205
- name: mimemagic
205
+ name: mini_magick
206
206
  requirement: !ruby/object:Gem::Requirement
207
207
  requirements:
208
208
  - - "~>"
209
209
  - !ruby/object:Gem::Version
210
- version: 0.3.2
210
+ version: '4.9'
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: 4.9.4
211
214
  type: :runtime
212
215
  prerelease: false
213
216
  version_requirements: !ruby/object:Gem::Requirement
214
217
  requirements:
215
218
  - - "~>"
216
219
  - !ruby/object:Gem::Version
217
- version: 0.3.2
220
+ version: '4.9'
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ version: 4.9.4
218
224
  - !ruby/object:Gem::Dependency
219
- name: mini_magick
225
+ name: nokogiri
220
226
  requirement: !ruby/object:Gem::Requirement
221
227
  requirements:
222
- - - "~>"
223
- - !ruby/object:Gem::Version
224
- version: '4.9'
225
228
  - - ">="
226
229
  - !ruby/object:Gem::Version
227
- version: 4.9.4
230
+ version: 1.12.5
228
231
  type: :runtime
229
232
  prerelease: false
230
233
  version_requirements: !ruby/object:Gem::Requirement
231
234
  requirements:
232
- - - "~>"
233
- - !ruby/object:Gem::Version
234
- version: '4.9'
235
235
  - - ">="
236
236
  - !ruby/object:Gem::Version
237
- version: 4.9.4
237
+ version: 1.12.5
238
238
  - !ruby/object:Gem::Dependency
239
239
  name: rack
240
240
  requirement: !ruby/object:Gem::Requirement
@@ -255,20 +255,14 @@ dependencies:
255
255
  requirements:
256
256
  - - "~>"
257
257
  - !ruby/object:Gem::Version
258
- version: 5.2.4
259
- - - ">="
260
- - !ruby/object:Gem::Version
261
- version: 5.2.4.3
258
+ version: 5.2.6
262
259
  type: :runtime
263
260
  prerelease: false
264
261
  version_requirements: !ruby/object:Gem::Requirement
265
262
  requirements:
266
263
  - - "~>"
267
264
  - !ruby/object:Gem::Version
268
- version: 5.2.4
269
- - - ">="
270
- - !ruby/object:Gem::Version
271
- version: 5.2.4.3
265
+ version: 5.2.6
272
266
  - !ruby/object:Gem::Dependency
273
267
  name: rails_autolink
274
268
  requirement: !ruby/object:Gem::Requirement
@@ -700,6 +694,7 @@ files:
700
694
  - app/controllers/text_controller.rb
701
695
  - app/controllers/textfilter_controller.rb
702
696
  - app/controllers/theme_controller.rb
697
+ - app/controllers/users/registrations_controller.rb
703
698
  - app/controllers/xml_controller.rb
704
699
  - app/helpers/admin/base_helper.rb
705
700
  - app/helpers/admin/feedback_helper.rb
@@ -974,6 +969,7 @@ files:
974
969
  - lib/publify_core/testing_support/feed_assertions.rb
975
970
  - lib/publify_core/testing_support/fixtures/exploit.svg
976
971
  - lib/publify_core/testing_support/fixtures/fakepng.png
972
+ - lib/publify_core/testing_support/fixtures/just_some.html
977
973
  - lib/publify_core/testing_support/fixtures/otherfile.txt
978
974
  - lib/publify_core/testing_support/fixtures/testfile.png
979
975
  - lib/publify_core/testing_support/fixtures/testfile.txt
@@ -1004,7 +1000,7 @@ homepage: https://publify.github.io/
1004
1000
  licenses:
1005
1001
  - MIT
1006
1002
  metadata: {}
1007
- post_install_message:
1003
+ post_install_message:
1008
1004
  rdoc_options: []
1009
1005
  require_paths:
1010
1006
  - lib
@@ -1012,15 +1008,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
1012
1008
  requirements:
1013
1009
  - - ">="
1014
1010
  - !ruby/object:Gem::Version
1015
- version: 2.4.0
1011
+ version: 2.5.0
1016
1012
  required_rubygems_version: !ruby/object:Gem::Requirement
1017
1013
  requirements:
1018
1014
  - - ">="
1019
1015
  - !ruby/object:Gem::Version
1020
1016
  version: '0'
1021
1017
  requirements: []
1022
- rubygems_version: 3.2.3
1023
- signing_key:
1018
+ rubygems_version: 3.1.6
1019
+ signing_key:
1024
1020
  specification_version: 4
1025
1021
  summary: Core engine for the Publify blogging system.
1026
1022
  test_files: []