jekyll_flexible_include 2.0.8 → 2.0.11

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64eb6af1f283738c8152205359b97b42081c571cc8cd16dc30d263108e21aba0
4
- data.tar.gz: 87b46d76f2f43022c458fff1dc4f3ea5523ccc0afe29ca7eb4c6c7f41554427d
3
+ metadata.gz: f3c2d80bab20b338d7635734938862e2ed99af858dc8f4967e7f0995fc0e5304
4
+ data.tar.gz: 3683ddcebf92f60dd12955e34eb64a910e8d51a16e46fa2b8c40fafb5b33b682
5
5
  SHA512:
6
- metadata.gz: 143e9c8cc4e9d5a109ce41020e46c4c8c0366e9c30bf4201263767e5276818ca32293430d6464afbea3a1925c90256219394dcf77b57735dd49ff3efa42dd940
7
- data.tar.gz: 2dd1b9df7fa2936231ef0bb85ef8ecb87fc7afa9d519a9fda3dd9167869b13671c9ece3c13b1576ac11d9c0abc1adc498e7bc66fd5fb3fdb9634e417666119a6
6
+ metadata.gz: 694653b9d9104793c425af90a2f93be38ee822c399bc60b1ce1bb012f70ea8af0268a8d4679353a4aab1f0dcd143b8738f58c74e094dc973b27081ac46690abd
7
+ data.tar.gz: 38b218be26c2bef642f13bf313150ef92676d214d5ade4b8333d936e47883f5b2a8b941b4a67f58427794706b68e976cd04847a1efba286dabe3d25eb914b3a9
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 2.0.11 / 2022-04-15
2
+ * Added & => & to the escaped characters
3
+
4
+ ## 2.0.10 / 2022-04-15
5
+ * Fixed nil pointer
6
+
7
+ ## 2.0.9 / 2022-04-15
8
+ * Changed how path matching was implemented.
9
+
1
10
  ## 2.0.8 / 2022-04-14
2
11
  * Added the ability to restrict arbitrary command execution, and specify the allowable directories to read from.
3
12
 
data/README.md CHANGED
@@ -60,7 +60,7 @@ For example, the following restricts access to only the files within:
60
60
  2. The directory tree rooted at `/var/files`.
61
61
  3. The directory tree rooted at the expanded value of the `$work` environment variable.
62
62
  ```shell
63
- export FLEXIBLE_INCLUDE_PATHS='~/my_dir/**/{*,.*}:/var/files/**/{*,.*}:$work/**/{*,.*}'
63
+ export FLEXIBLE_INCLUDE_PATHS='~/.*:$sites/.*:$work/.*'
64
64
  ```
65
65
  Note that the above matches dot (hidden) files as well as regular files.
66
66
  To just match visible files:
@@ -68,6 +68,9 @@ To just match visible files:
68
68
  export FLEXIBLE_INCLUDE_PATHS='~/my_dir/**/*:/var/files/**/*:$work/**/*'
69
69
  ```
70
70
 
71
+ #### Note
72
+ The specified directories are traversed when the plugin starts, and the filenames are stored in memory. Directories with lots of files might take a noticable amount to time to enumerate the files.
73
+
71
74
 
72
75
  ### Restricting Arbitrary Processes
73
76
  By default, `flexible_include` can execute any command. You can disable that by setting the environment variable `DISABLE_FLEXIBLE_INCLUDE` to any non-empty value.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllFlexibleIncludePluginVersion
4
- VERSION = "2.0.8"
4
+ VERSION = "2.0.11"
5
5
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "benchmark"
3
4
  require "jekyll"
4
5
  require "jekyll_plugin_logger"
5
6
  require "securerandom"
@@ -13,6 +14,36 @@ end
13
14
  class FlexibleInclude < Liquid::Tag
14
15
  FlexibleIncludeError = Class.new(Liquid::Error)
15
16
 
17
+ @read_regexes = nil
18
+
19
+ def self.normalize_path(path)
20
+ JekyllTagHelper.expand_env(path)
21
+ .gsub("~", Dir.home)
22
+ end
23
+
24
+ # If FLEXIBLE_INCLUDE_PATHS='~/lib/.*:.*:$WORK/.*'
25
+ # Then @read_regexes will be set to regexes of ["/home/my_user_id/lib/.*", "/pwd/.*", "/work/envar/path/.*"]
26
+ def self.security_check
27
+ @execution_denied = ENV['DISABLE_FLEXIBLE_INCLUDE']
28
+
29
+ unless @read_regexes
30
+ flexible_include_paths = ENV['FLEXIBLE_INCLUDE_PATHS']
31
+ read_paths = normalize_path(flexible_include_paths) if flexible_include_paths
32
+ if read_paths
33
+ @read_regexes = read_paths.split(":").map do |path|
34
+ abs_path = path.start_with?('/') ? path : (Pathname.new(Dir.pwd) + path).to_s
35
+ Regexp.new(abs_path)
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def self.access_allowed(path)
42
+ return true unless @read_regexes
43
+
44
+ @read_regexes.find { |regex| regex.match(normalize_path(path)) }
45
+ end
46
+
16
47
  # @param tag_name [String] the name of the tag, which we already know.
17
48
  # @param markup [String] the arguments from the tag, as a single string.
18
49
  # @param parse_context [Liquid::ParseContext] hash that stores Liquid options.
@@ -25,12 +56,7 @@ class FlexibleInclude < Liquid::Tag
25
56
  @logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
26
57
  @helper = JekyllTagHelper.new(tag_name, markup, @logger)
27
58
 
28
- @execution_denied = ENV['DISABLE_FLEXIBLE_INCLUDE']
29
-
30
- # If FLEXIBLE_INCLUDE_PATHS='~/lib/**/*:*/**/*'
31
- # Then @read_paths will be set to ["~/lib/**/*", "*/**/*"]
32
- @read_paths = ENV['FLEXIBLE_INCLUDE_PATHS']
33
- @read_paths = @read_paths.split(":").map { |x| JekyllTagHelper.expand_env x } if @read_paths
59
+ self.class.security_check
34
60
  end
35
61
 
36
62
  # @param liquid_context [Liquid::Context]
@@ -43,6 +69,7 @@ class FlexibleInclude < Liquid::Tag
43
69
  @label_specified = @label
44
70
  @copy_button = @helper.parameter_specified? "copyButton"
45
71
  @pre = @copy_button || @dark || @download || @label_specified || @helper.parameter_specified?("pre") # Download or label implies pre
72
+
46
73
  filename = @helper.parameter_specified? "file"
47
74
  filename ||= @helper.params.first # Do this after all options have been checked for
48
75
  @label ||= filename
@@ -55,16 +82,19 @@ class FlexibleInclude < Liquid::Tag
55
82
  path = JekyllTagHelper.expand_env(filename)
56
83
  case path
57
84
  when /\A\// # Absolute path
58
- return denied("Access to #{path} denied by FLEXIBLE_INCLUDE_PATHS value.") unless access_allowed(path)
85
+ return denied("Access to #{path} denied by FLEXIBLE_INCLUDE_PATHS value.") unless self.class.access_allowed(path)
86
+
59
87
  @logger.debug { "Absolute path=#{path}, filename=#{filename}" }
60
88
  when /\A~/ # Relative path to user's home directory
61
- return denied("Access to #{path} denied by FLEXIBLE_INCLUDE_PATHS value.") unless access_allowed(path)
89
+ return denied("Access to #{path} denied by FLEXIBLE_INCLUDE_PATHS value.") unless self.class.access_allowed(path)
90
+
62
91
  @logger.debug { "User home start filename=#{filename}, path=#{path}" }
63
92
  filename.slice! "~/"
64
93
  path = File.join(ENV['HOME'], filename)
65
94
  @logger.debug { "User home end filename=#{filename}, path=#{path}" }
66
95
  when /\A!/ # Run command and return response
67
96
  return denied("Arbitrary command execution denied by DISABLE_FLEXIBLE_INCLUDE value.") if @execution_denied
97
+
68
98
  filename = JekyllTagHelper.remove_quotes(@helper.argv.first) if @helper.argv.first
69
99
  filename.slice! "!"
70
100
  contents = run(filename)
@@ -82,11 +112,6 @@ class FlexibleInclude < Liquid::Tag
82
112
 
83
113
  private
84
114
 
85
- def access_allowed(path)
86
- return true unless @read_paths
87
- Dir.glob(@read_paths).find { |x| x == path }
88
- end
89
-
90
115
  def denied(msg)
91
116
  @logger.error("#{@helper.page.path} - #{msg}")
92
117
  "<p style='color: white; background-color: red; padding: 2pt 1em 2pt 1em;'>#{msg}</p>"
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "shellwords"
4
+ require 'key_value_parser'
4
5
 
5
6
  class JekyllTagHelper
6
7
  attr_reader :argv, :liquid_context, :logger, :params, :tag_name
7
8
 
8
9
  def self.escape_html(string)
9
- string.gsub("{", "&#123;").gsub("}", "&#125;").gsub("<", "&lt;")
10
+ string.gsub("&", "&amp;")
11
+ .gsub("{", "&#123;")
12
+ .gsub("}", "&#125;")
13
+ .gsub("<", "&lt;")
10
14
  end
11
15
 
12
16
  # Expand a environment variable reference
data/spec/glob_spec.rb ADDED
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../lib/flexible_include"
4
+
5
+ RSpec.describe(FlexibleInclude) do
6
+ it "controls access to files" do
7
+ ENV['FLEXIBLE_INCLUDE_PATHS'] = '~/.*:spec/.*'
8
+
9
+ FlexibleInclude.send(:new, 'my_tag', "", Liquid::ParseContext.new)
10
+ FlexibleInclude.security_check
11
+ expect(FlexibleInclude.access_allowed(__FILE__)).to be_truthy
12
+
13
+ expect(FlexibleInclude.access_allowed("~/.mem_settings.yaml")).to be_truthy
14
+
15
+ home_file = JekyllTagHelper.expand_env("$HOME/.mem_settings.yaml")
16
+ expect(FlexibleInclude.access_allowed(home_file)).to be_truthy
17
+
18
+ expect(FlexibleInclude.access_allowed('/asdf')).to be_falsey
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jekyll"
4
+
5
+ require_relative "../lib/flexible_include"
6
+
7
+ Jekyll.logger.log_level = :info
8
+
9
+ RSpec.configure do |config|
10
+ config.filter_run :focus
11
+ config.order = "random"
12
+ config.run_all_when_everything_filtered = true
13
+
14
+ # See https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures
15
+ config.example_status_persistence_file_path = "spec/status_persistence.txt"
16
+ end
@@ -0,0 +1,3 @@
1
+ example_id | status | run_time |
2
+ ------------------------ | ------ | --------------- |
3
+ ./spec/glob_spec.rb[1:1] | passed | 0.01217 seconds |
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll_flexible_include
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.8
4
+ version: 2.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Slinn
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-04-14 00:00:00.000000000 Z
13
+ date: 2022-04-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: jekyll
@@ -88,6 +88,9 @@ files:
88
88
  - lib/flexible_include.rb
89
89
  - lib/flexible_include/version.rb
90
90
  - lib/jekyll_tag_helper.rb
91
+ - spec/glob_spec.rb
92
+ - spec/spec_helper.rb
93
+ - spec/status_persistence.txt
91
94
  homepage: https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html#flexibleInclude
92
95
  licenses:
93
96
  - MIT
@@ -120,4 +123,7 @@ signing_key:
120
123
  specification_version: 4
121
124
  summary: Jekyll plugin supports various ways to include content into the generated
122
125
  site.
123
- test_files: []
126
+ test_files:
127
+ - spec/glob_spec.rb
128
+ - spec/spec_helper.rb
129
+ - spec/status_persistence.txt