jekyll_flexible_include 2.0.8 → 2.0.11

Sign up to get free protection for your applications and to get access to all the features.
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