diff --git a/features/site_configuration.feature b/features/site_configuration.feature index 4052315d..0a08f753 100644 --- a/features/site_configuration.feature +++ b/features/site_configuration.feature @@ -233,3 +233,26 @@ Feature: Site configuration Then the _site directory should exist And I should see "Whatever" in "_site/index.html" And I should see "this is a test" in "_site/test.txt" + + Scenario: Add an empty whitelist to restrict all gems + Given I have an "index.html" file that contains "Whatever" + And I have a configuration file with: + | key | value | + | gems | [jekyll_test_plugin] | + | whitelist | [] | + When I run jekyll in safe mode + Then the _site directory should exist + And I should see "Whatever" in "_site/index.html" + And the "_site/test.txt" file should not exist + + Scenario: Add a whitelist to restrict some gems but allow others + Given I have an "index.html" file that contains "Whatever" + And I have a configuration file with: + | key | value | + | gems | [jekyll_test_plugin, jekyll_test_plugin_malicious] | + | whitelist | [jekyll_test_plugin] | + When I run jekyll in safe mode + Then the _site directory should exist + And I should see "Whatever" in "_site/index.html" + And the "_site/test.txt" file should exist + And I should see "this is a test" in "_site/test.txt" diff --git a/features/step_definitions/jekyll_steps.rb b/features/step_definitions/jekyll_steps.rb index 7a74486b..43c7e31d 100644 --- a/features/step_definitions/jekyll_steps.rb +++ b/features/step_definitions/jekyll_steps.rb @@ -1,9 +1,13 @@ Before do - FileUtils.rm_rf(TEST_DIR) FileUtils.mkdir(TEST_DIR) Dir.chdir(TEST_DIR) end +After do + FileUtils.rm_rf(TEST_DIR) + FileUtils.rm_rf(JEKYLL_COMMAND_OUTPUT_FILE) +end + World(Test::Unit::Assertions) Given /^I have a blank site in "(.*)"$/ do |path| @@ -123,19 +127,23 @@ end When /^I run jekyll$/ do - run_jekyll + run_jekyll_build +end + +When /^I run jekyll in safe mode$/ do + run_jekyll_build("--safe") end When /^I run jekyll with drafts$/ do - run_jekyll(:drafts => true) + run_jekyll_build("--drafts") end When /^I call jekyll new with test_blank --blank$/ do - call_jekyll_new(:path => "test_blank", :blank => true) + run_jekyll_new("test_blank --blank") end When /^I debug jekyll$/ do - run_jekyll(:debug => true) + run_jekyll_build("--verbose") end When /^I change "(.*)" to contain "(.*)"$/ do |file, text| diff --git a/features/support/env.rb b/features/support/env.rb index 0d207b41..cf2055a1 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -10,22 +10,31 @@ require 'time' TEST_DIR = File.join('/', 'tmp', 'jekyll') JEKYLL_PATH = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'jekyll') +JEKYLL_COMMAND_OUTPUT_FILE = File.join('/', 'tmp', 'jekyll_output.txt') -def run_jekyll(opts = {}) - command = JEKYLL_PATH.clone - command << " build" - command << " --drafts" if opts[:drafts] - command << " >> /dev/null 2>&1" if opts[:debug].nil? +def jekyll_output_file + JEKYLL_COMMAND_OUTPUT_FILE +end + +def jekyll_run_output + File.read(jekyll_output_file) +end + +def run_jekyll(args, output_file) + command = "#{JEKYLL_PATH} #{args} > #{jekyll_output_file} 2>&1" system command end -def call_jekyll_new(opts = {}) - command = JEKYLL_PATH.clone - command << " new" - command << " #{opts[:path]}" if opts[:path] - command << " --blank" if opts[:blank] - command << " >> /dev/null 2>&1" if opts[:debug].nil? - system command +def run_jekyll_build(build_args = "") + if !run_jekyll("build #{build_args}", jekyll_output_file) || build_args.eql?("--verbose") + puts jekyll_run_output + end +end + +def run_jekyll_new(new_args = "") + unless run_jekyll("new #{new_args}", jekyll_output_file) + puts jekyll_run_output + end end def slug(title) diff --git a/jekyll.gemspec b/jekyll.gemspec index 9176f2fa..52470602 100644 --- a/jekyll.gemspec +++ b/jekyll.gemspec @@ -50,6 +50,7 @@ Gem::Specification.new do |s| s.add_development_dependency('mime-types', "~> 1.5") s.add_development_dependency('activesupport', '~> 3.2.13') s.add_development_dependency('jekyll_test_plugin') + s.add_development_dependency('jekyll_test_plugin_malicious') # = MANIFEST = s.files = %w[ diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 74d10fd5..3201a9df 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -77,11 +77,10 @@ module Jekyll require f end end - self.gems.each do |gem| - require gem - end end + require_gems + self.converters = instantiate_subclasses(Jekyll::Converter) self.generators = instantiate_subclasses(Jekyll::Generator) end @@ -97,6 +96,22 @@ module Jekyll end end + def require_gems + self.gems.each do |gem| + if plugin_allowed?(gem) + require gem + end + end + end + + def plugin_allowed?(gem_name) + whitelist.include?(gem_name) || !self.safe + end + + def whitelist + @whitelist ||= Array[self.config['whitelist']].flatten || [] + end + # Internal: Setup the plugin search path # # Returns an Array of plugin search paths