mirror of
https://github.com/jekyll/jekyll.git
synced 2026-04-28 03:01:03 -04:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e20ced151 | ||
|
|
13742c7503 | ||
|
|
73beb3986a | ||
|
|
a5e0403d1d | ||
|
|
6eccb11d88 | ||
|
|
fbc2c7e56e | ||
|
|
4df2b9346a | ||
|
|
53259039a4 | ||
|
|
71bb0289e5 | ||
|
|
780c9302f4 | ||
|
|
b55fb3d816 | ||
|
|
3901c88805 | ||
|
|
10d1f49902 | ||
|
|
98b366e5d5 | ||
|
|
b1a7e145c0 | ||
|
|
6277335ba0 | ||
|
|
e7cf42b624 | ||
|
|
69b439904b | ||
|
|
033971053e | ||
|
|
93a6d4d9c0 | ||
|
|
827eed78b9 | ||
|
|
a06dff4eca | ||
|
|
823f875836 | ||
|
|
4af594916f | ||
|
|
92da39eb6f | ||
|
|
f8983194c8 | ||
|
|
b716cc62fe | ||
|
|
24495c6355 | ||
|
|
8d6c09cc4f | ||
|
|
9cc1a8f178 | ||
|
|
0d6b208380 | ||
|
|
3fdc91eb78 | ||
|
|
6b0c511b9d | ||
|
|
aa5c98d281 | ||
|
|
eb54b7f90d | ||
|
|
e92b67dfb9 | ||
|
|
3a870fd09e | ||
|
|
3607ac5e5f | ||
|
|
ca95e75976 |
@@ -10,6 +10,22 @@
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
## 1.4.3 / 2014-01-13
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Patch show-stopping security vulnerabilities (#1944)
|
||||
|
||||
## 1.4.2 / 2013-12-16
|
||||
|
||||
### Bug Fixes
|
||||
* Turn on Maruku fenced code blocks by default (#1830)
|
||||
|
||||
## 1.4.1 / 2013-12-09
|
||||
|
||||
### Bug Fixes
|
||||
* Don't allow nil entries when loading posts (#1796)
|
||||
|
||||
## 1.4.0 / 2013-12-07
|
||||
|
||||
### Major Enhancements
|
||||
|
||||
6
Rakefile
6
Rakefile
@@ -233,7 +233,7 @@ namespace :site do
|
||||
post.puts("title: 'Jekyll #{release} Released'")
|
||||
post.puts("date: #{Time.new.strftime('%Y-%m-%d %H:%M:%S %z')}")
|
||||
post.puts("author: ")
|
||||
post.puts("version: #{version}")
|
||||
post.puts("version: #{release}")
|
||||
post.puts("categories: [release]")
|
||||
post.puts("---")
|
||||
post.puts
|
||||
@@ -252,8 +252,8 @@ end
|
||||
#############################################################################
|
||||
|
||||
task :release => :build do
|
||||
unless `git branch` =~ /^\* master$/
|
||||
puts "You must be on the master branch to release!"
|
||||
unless `git branch` =~ /^(\* master|\* v1-stable)$/
|
||||
puts "You must be on the master branch or the v1-stable branch to release!"
|
||||
exit!
|
||||
end
|
||||
sh "git commit --allow-empty -m 'Release #{version}'"
|
||||
|
||||
@@ -28,3 +28,40 @@ Feature: Markdown
|
||||
And I should see "Index" in "_site/index.html"
|
||||
And I should see "<h1 id=\"my_title\">My Title</h1>" in "_site/index.html"
|
||||
|
||||
Scenario: Maruku fenced codeblocks
|
||||
Given I have a configuration file with "markdown" set to "maruku"
|
||||
And I have an "index.markdown" file with content:
|
||||
"""
|
||||
---
|
||||
title: My title
|
||||
---
|
||||
|
||||
# My title
|
||||
|
||||
```
|
||||
My awesome code
|
||||
```
|
||||
"""
|
||||
When I run jekyll
|
||||
Then the _site directory should exist
|
||||
And I should see "My awesome code" in "_site/index.html"
|
||||
And I should see "<pre><code>\nMy awesome code\n</code></pre>" in "_site/index.html"
|
||||
|
||||
Scenario: Maruku fenced codeblocks
|
||||
Given I have a configuration file with "markdown" set to "maruku"
|
||||
And I have an "index.markdown" file with content:
|
||||
"""
|
||||
---
|
||||
title: My title
|
||||
---
|
||||
|
||||
# My title
|
||||
|
||||
```ruby
|
||||
puts "My awesome string"
|
||||
```
|
||||
"""
|
||||
When I run jekyll
|
||||
Then the _site directory should exist
|
||||
And I should see "My awesome string" in "_site/index.html"
|
||||
And I should see "<pre class="ruby"><code class="ruby">\nputs "My awesome string"\n</code></pre>" in "_site/index.html"
|
||||
|
||||
@@ -4,9 +4,9 @@ Gem::Specification.new do |s|
|
||||
s.rubygems_version = '1.3.5'
|
||||
|
||||
s.name = 'jekyll'
|
||||
s.version = '1.4.0'
|
||||
s.version = '1.4.3'
|
||||
s.license = 'MIT'
|
||||
s.date = '2013-12-07'
|
||||
s.date = '2014-01-13'
|
||||
s.rubyforge_project = 'jekyll'
|
||||
|
||||
s.summary = "A simple, blog aware, static site generator."
|
||||
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.extra_rdoc_files = %w[README.markdown LICENSE]
|
||||
|
||||
s.add_runtime_dependency('liquid', "~> 2.5.2")
|
||||
s.add_runtime_dependency('liquid', "~> 2.5.5")
|
||||
s.add_runtime_dependency('classifier', "~> 1.3")
|
||||
s.add_runtime_dependency('listen', "~> 1.3")
|
||||
s.add_runtime_dependency('maruku', "~> 0.7.0")
|
||||
@@ -160,6 +160,8 @@ Gem::Specification.new do |s|
|
||||
site/_posts/2013-11-04-jekyll-1-3-0-released.markdown
|
||||
site/_posts/2013-11-26-jekyll-1-3-1-released.markdown
|
||||
site/_posts/2013-12-07-jekyll-1-4-0-released.markdown
|
||||
site/_posts/2013-12-16-jekyll-1-4-2-released.markdown
|
||||
site/_posts/2014-01-13-jekyll-1-4-3-released.markdown
|
||||
site/css/gridism.css
|
||||
site/css/normalize.css
|
||||
site/css/pygments.css
|
||||
@@ -219,6 +221,7 @@ Gem::Specification.new do |s|
|
||||
test/source/_data/products.yml
|
||||
test/source/_includes/params.html
|
||||
test/source/_includes/sig.markdown
|
||||
test/source/_includes/tmp
|
||||
test/source/_layouts/default.html
|
||||
test/source/_layouts/post/simple.html
|
||||
test/source/_layouts/simple.html
|
||||
@@ -256,6 +259,7 @@ Gem::Specification.new do |s|
|
||||
test/source/_posts/2013-05-10-number-category.textile
|
||||
test/source/_posts/2013-07-22-post-excerpt-with-layout.markdown
|
||||
test/source/_posts/2013-08-01-mkdn-extension.mkdn
|
||||
test/source/_posts/2014-01-06-permalink-traversal.md
|
||||
test/source/_posts/es/2008-11-21-nested.textile
|
||||
test/source/about.html
|
||||
test/source/category/_posts/2008-9-23-categories.textile
|
||||
@@ -264,6 +268,7 @@ Gem::Specification.new do |s|
|
||||
test/source/contacts/index.html
|
||||
test/source/css/screen.css
|
||||
test/source/deal.with.dots.html
|
||||
test/source/exploit.md
|
||||
test/source/foo/_posts/bar/2008-12-12-topical-post.textile
|
||||
test/source/index.html
|
||||
test/source/products.yml
|
||||
|
||||
@@ -63,7 +63,7 @@ require_all 'jekyll/tags'
|
||||
SafeYAML::OPTIONS[:suppress_warnings] = true
|
||||
|
||||
module Jekyll
|
||||
VERSION = '1.4.0'
|
||||
VERSION = '1.4.3'
|
||||
|
||||
# Public: Generate a Jekyll configuration Hash by merging the default
|
||||
# options with anything in _config.yml, and adding the given options on top.
|
||||
|
||||
@@ -45,6 +45,7 @@ module Jekyll
|
||||
'excerpt_separator' => "\n\n",
|
||||
|
||||
'maruku' => {
|
||||
'fenced_code_blocks' => true,
|
||||
'use_tex' => false,
|
||||
'use_divs' => false,
|
||||
'png_engine' => 'blahtex',
|
||||
|
||||
@@ -8,6 +8,7 @@ module Jekyll
|
||||
@errors = []
|
||||
load_divs_library if @config['maruku']['use_divs']
|
||||
load_blahtext_library if @config['maruku']['use_tex']
|
||||
enable_fenced_code_blocks if @config['maruku']['fenced_code_blocks']
|
||||
rescue LoadError
|
||||
STDERR.puts 'You are missing a library required for Markdown. Please run:'
|
||||
STDERR.puts ' $ [sudo] gem install maruku'
|
||||
@@ -35,6 +36,10 @@ module Jekyll
|
||||
MaRuKu::Globals[:html_png_url] = @config['maruku']['png_url']
|
||||
end
|
||||
|
||||
def enable_fenced_code_blocks
|
||||
MaRuKu::Globals[:fenced_code_blocks] = true
|
||||
end
|
||||
|
||||
def print_errors_and_fail
|
||||
print @errors.join
|
||||
raise MaRuKu::Exception, "MaRuKu encountered problem(s) while converting your markup."
|
||||
|
||||
@@ -78,6 +78,10 @@ class File
|
||||
def self.read_with_options(path, opts = {})
|
||||
self.read(path)
|
||||
end
|
||||
|
||||
def self.realpath(filename)
|
||||
Pathname.new(filename).realpath.to_s
|
||||
end
|
||||
else
|
||||
def self.read_with_options(path, opts = {})
|
||||
self.read(path, opts)
|
||||
|
||||
@@ -133,7 +133,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the destination file path String.
|
||||
def destination(dest)
|
||||
path = File.join(dest, self.url)
|
||||
path = File.join(dest, File.expand_path(self.url, "/"))
|
||||
path = File.join(path, "index.html") if self.url =~ /\/$/
|
||||
path
|
||||
end
|
||||
|
||||
@@ -266,7 +266,7 @@ module Jekyll
|
||||
# Returns destination file path String.
|
||||
def destination(dest)
|
||||
# The url needs to be unescaped in order to preserve the correct filename
|
||||
path = File.join(dest, CGI.unescape(self.url))
|
||||
path = File.join(dest, File.expand_path(CGI.unescape(self.url), "/"))
|
||||
path = File.join(path, "index.html") if path[/\.html$/].nil?
|
||||
path
|
||||
end
|
||||
|
||||
@@ -193,8 +193,10 @@ module Jekyll
|
||||
end
|
||||
|
||||
def read_things(dir, magic_dir, klass)
|
||||
things = get_entries(dir, magic_dir).map do |entry|
|
||||
get_entries(dir, magic_dir).map do |entry|
|
||||
klass.new(self, self.source, dir, entry) if klass.valid?(entry)
|
||||
end.reject do |entry|
|
||||
entry.nil?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -87,14 +87,13 @@ eos
|
||||
end
|
||||
|
||||
def render(context)
|
||||
dir = File.join(context.registers[:site].source, INCLUDES_DIR)
|
||||
validate_dir(dir, context.registers[:site].safe)
|
||||
dir = File.join(File.realpath(context.registers[:site].source), INCLUDES_DIR)
|
||||
|
||||
file = retrieve_variable(context) || @file
|
||||
validate_file_name(file)
|
||||
|
||||
path = File.join(dir, file)
|
||||
validate_file(path, context.registers[:site].safe)
|
||||
validate_path(path, dir, context.registers[:site].safe)
|
||||
|
||||
begin
|
||||
partial = Liquid::Template.parse(source(path, context))
|
||||
@@ -108,18 +107,16 @@ eos
|
||||
end
|
||||
end
|
||||
|
||||
def validate_dir(dir, safe)
|
||||
if File.symlink?(dir) && safe
|
||||
raise IOError.new "Includes directory '#{dir}' cannot be a symlink"
|
||||
def validate_path(path, dir, safe)
|
||||
if safe && !realpath_prefixed_with?(path, dir)
|
||||
raise IOError.new "The included file '#{path}' should exist and should not be a symlink"
|
||||
elsif !File.exist?(path)
|
||||
raise IOError.new "Included file '#{path}' not found"
|
||||
end
|
||||
end
|
||||
|
||||
def validate_file(file, safe)
|
||||
if !File.exists?(file)
|
||||
raise IOError.new "Included file '#{@file}' not found in '#{INCLUDES_DIR}' directory"
|
||||
elsif File.symlink?(file) && safe
|
||||
raise IOError.new "The included file '#{INCLUDES_DIR}/#{@file}' should not be a symlink"
|
||||
end
|
||||
def realpath_prefixed_with?(path, dir)
|
||||
File.exist?(path) && File.realpath(path).start_with?(dir)
|
||||
end
|
||||
|
||||
def blank?
|
||||
|
||||
@@ -50,6 +50,7 @@ module Jekyll
|
||||
|
||||
# Returns a sanitized String URL
|
||||
def sanitize_url(in_url)
|
||||
|
||||
# Remove all double slashes
|
||||
url = in_url.gsub(/\/\//, "/")
|
||||
|
||||
@@ -61,6 +62,7 @@ module Jekyll
|
||||
|
||||
# Always add a leading slash
|
||||
url.gsub!(/\A([^\/])/, '/\1')
|
||||
|
||||
url
|
||||
end
|
||||
end
|
||||
|
||||
18
site/_posts/2013-12-16-jekyll-1-4-2-released.markdown
Normal file
18
site/_posts/2013-12-16-jekyll-1-4-2-released.markdown
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
layout: news_item
|
||||
title: 'Jekyll 1.4.2 Released'
|
||||
date: 2013-12-16 19:48:13 -0500
|
||||
author: parkr
|
||||
version: 1.4.2
|
||||
categories: [release]
|
||||
---
|
||||
|
||||
This release fixes [a regression][] where Maruku fenced code blocks were turned
|
||||
off, instead of the previous default to on. We've added a new default
|
||||
configuration to our `maruku` config key: `fenced_code_blocks` and set it to
|
||||
default to `true`.
|
||||
|
||||
If you do not wish to use Maruku fenced code blocks, you may turn this option
|
||||
off in your site's configuration file.
|
||||
|
||||
[a regression]: https://github.com/jekyll/jekyll/pull/1830
|
||||
27
site/_posts/2014-01-13-jekyll-1-4-3-released.markdown
Normal file
27
site/_posts/2014-01-13-jekyll-1-4-3-released.markdown
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
layout: news_item
|
||||
title: 'Jekyll 1.4.3 Released'
|
||||
date: 2014-01-13 17:43:32 -0800
|
||||
author: benbalter
|
||||
version: 1.4.3
|
||||
categories: [release]
|
||||
---
|
||||
|
||||
Jekyll 1.4.3 contains two **critical** security fixes. If you run Jekyll locally
|
||||
and do not run Jekyll in "safe" mode (e.g. you do not build Jekyll sites on behalf
|
||||
of others), you are not affected and are not required to update at this time.
|
||||
([See pull request.]({{ site.repository }}/pull/1944))
|
||||
|
||||
Versions of Jekyll prior to 1.4.3 and greater than 1.2.0 may allow malicious
|
||||
users to expose the content of files outside the source directory in the
|
||||
generated output via improper symlink sanitization, potentially resulting in an
|
||||
inadvertent information disclosure.
|
||||
|
||||
Versions of Jekyll prior to 1.4.3 may also allow malicious users to write
|
||||
arbitrary `.html` files outside of the destination folder via relative path
|
||||
traversal, potentially overwriting otherwise-trusted content with arbitrary HTML
|
||||
or Javascript depending on your server's configuration.
|
||||
|
||||
*Maintainer's note: Many thanks to @gregose and @charliesome for discovering
|
||||
these vulnerabilities, and to @BenBalter and @alindeman for writing the patch.
|
||||
-@parkr*
|
||||
@@ -316,6 +316,7 @@ maruku:
|
||||
png_engine: blahtex
|
||||
png_dir: images/latex
|
||||
png_url: /images/latex
|
||||
fenced_code_blocks: true
|
||||
|
||||
rdiscount:
|
||||
extensions: []
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
---
|
||||
layout: docs
|
||||
title: History
|
||||
permalink: /docs/history/
|
||||
---
|
||||
prev_section: contributing
|
||||
title: History
|
||||
layout: docs
|
||||
permalink: /docs/history/
|
||||
---
|
||||
|
||||
## 1.4.3 / 2014-01-13
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Patch show-stopping security vulnerabilities ([#1944]({{ site.repository }}/issues/1944))
|
||||
|
||||
## 1.4.2 / 2013-12-16
|
||||
|
||||
### Bug Fixes
|
||||
- Turn on Maruku fenced code blocks by default ([#1830]({{ site.repository }}/issues/1830))
|
||||
|
||||
## 1.4.1 / 2013-12-09
|
||||
|
||||
### Bug Fixes
|
||||
- Don't allow nil entries when loading posts ([#1796]({{ site.repository }}/issues/1796))
|
||||
|
||||
## 1.4.0 / 2013-12-07
|
||||
|
||||
### Major Enhancements
|
||||
|
||||
1
test/source/_includes/tmp
Symbolic link
1
test/source/_includes/tmp
Symbolic link
@@ -0,0 +1 @@
|
||||
/tmp
|
||||
5
test/source/_posts/2014-01-06-permalink-traversal.md
Normal file
5
test/source/_posts/2014-01-06-permalink-traversal.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
permalink: /%2e%2e/%2e%2e/%2e%2e/baddie.html
|
||||
---
|
||||
|
||||
# Test
|
||||
5
test/source/exploit.md
Normal file
5
test/source/exploit.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
permalink: /%2e%2e/%2e%2e/%2e%2e/baddie.html
|
||||
---
|
||||
|
||||
# Test
|
||||
@@ -14,7 +14,7 @@ class TestGeneratedSite < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
should "ensure post count is as expected" do
|
||||
assert_equal 36, @site.posts.size
|
||||
assert_equal 37, @site.posts.size
|
||||
end
|
||||
|
||||
should "insert site.posts into the index" do
|
||||
|
||||
@@ -101,6 +101,16 @@ class TestPage < Test::Unit::TestCase
|
||||
assert_equal @page.permalink, @page.url
|
||||
assert_equal "/about/", @page.dir
|
||||
end
|
||||
|
||||
should "not be writable outside of destination" do
|
||||
unexpected = File.expand_path("../../../baddie.html", dest_dir)
|
||||
File.delete unexpected if File.exist?(unexpected)
|
||||
page = setup_page("exploit.md")
|
||||
do_render(page)
|
||||
page.write(dest_dir)
|
||||
|
||||
assert !File.exist?(unexpected)
|
||||
end
|
||||
end
|
||||
|
||||
context "with specified layout of nil" do
|
||||
|
||||
@@ -75,6 +75,17 @@ class TestPost < Test::Unit::TestCase
|
||||
assert_equal "/my_category/permalinked-post", @post.url
|
||||
end
|
||||
|
||||
should "not be writable outside of destination" do
|
||||
unexpected = File.expand_path("../../../baddie.html", dest_dir)
|
||||
File.delete unexpected if File.exist?(unexpected)
|
||||
post = setup_post("2014-01-06-permalink-traversal.md")
|
||||
do_render(post)
|
||||
post.write(dest_dir)
|
||||
|
||||
assert !File.exist?(unexpected)
|
||||
assert File.exist?(File.expand_path("baddie.html", dest_dir))
|
||||
end
|
||||
|
||||
context "with CRLF linebreaks" do
|
||||
setup do
|
||||
@real_file = "2009-05-24-yaml-linebreak.markdown"
|
||||
|
||||
@@ -347,6 +347,41 @@ CONTENT
|
||||
end
|
||||
|
||||
context "include tag with parameters" do
|
||||
|
||||
context "with symlink'd include" do
|
||||
|
||||
should "not allow symlink includes" do
|
||||
File.open("/tmp/pages-test", 'w') { |file| file.write("SYMLINK TEST") }
|
||||
assert_raise IOError do
|
||||
content = <<CONTENT
|
||||
---
|
||||
title: Include symlink
|
||||
---
|
||||
|
||||
{% include tmp/pages-test %}
|
||||
|
||||
CONTENT
|
||||
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true, 'safe' => true })
|
||||
end
|
||||
assert_no_match /SYMLINK TEST/, @result
|
||||
end
|
||||
|
||||
should "not expose the existence of symlinked files" do
|
||||
ex = assert_raise IOError do
|
||||
content = <<CONTENT
|
||||
---
|
||||
title: Include symlink
|
||||
---
|
||||
|
||||
{% include tmp/pages-test-does-not-exist %}
|
||||
|
||||
CONTENT
|
||||
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true, 'safe' => true })
|
||||
end
|
||||
assert_match /should exist and should not be a symlink/, ex.message
|
||||
end
|
||||
end
|
||||
|
||||
context "with one parameter" do
|
||||
setup do
|
||||
content = <<CONTENT
|
||||
|
||||
Reference in New Issue
Block a user