qiita-markdown 0.28.0 → 0.33.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of qiita-markdown might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db1f661355f65d7ca159db9a954a74002a39cb996e573aa483384edf7fb6f68c
4
- data.tar.gz: b2e6bce2f3f66af7e5238515e4f082abeedf86b90b886aacaa8ce45b7655e942
3
+ metadata.gz: 17dc016afba392cc6e3ea77af4cdc445e32c6004a6c23a24b8dce1a4e0ec1811
4
+ data.tar.gz: 042e3a11a8cc6d266463ae7bb8d3e46c8c732efeb061086586c80a277898cf38
5
5
  SHA512:
6
- metadata.gz: 9784da7558dbe61bcc6f4e3e923c3286f4954c9632b892997c3816b1e366844420cd8280ae432b8a6a85ec3dff543dd31aaf2690f6b2ed20ae862f9d756fb74c
7
- data.tar.gz: d1c1920577d61ba16cec374c16feaa9804e862b61e2653dfe99470b9832c66dc3d6c4969a8559b718bc3e0adf85b5e55aeb35604b01909a3c93b558a816e11e3
6
+ metadata.gz: 0c59646956b877c13e7c6ef62bd366483b5a7da78f19bfe8aee2305ea568c6f59dfb2d916e68a822e3363ddabbf7577166e8e21a8da79152550b11c77a3dc8d6
7
+ data.tar.gz: b907d5a284c9c77e9f264298d38d6ec4a0861179dda36320f6fd40187b606662b1e07e61d9f3e5bd2070f203e3de5d60b53cdb05593ca64ceb875c6bbd811f31
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 0.33.0
4
+
5
+ - Fix XSS possibility bug
6
+
7
+ ## 0.32.0
8
+
9
+ - Fix XSS possibility bug
10
+ - Fix iframe width to be fixed at 100%
11
+
12
+ ## 0.31.0
13
+
14
+ - Use greenmat 3.5.1.1
15
+
16
+ ## 0.30.0
17
+
18
+ - Use greenmat 3.5.1.0
19
+
20
+ ## 0.29.0
21
+
22
+ - Accept new embeded script and iframes
23
+ - Gist
24
+ - Youtube
25
+ - SlideShare
26
+ - SpeekerDeck
27
+ - GoogleSlide
28
+
3
29
  ## 0.28.0
4
30
 
5
31
  - Accept new codepen script url (cpwebassets.codepen.io)
@@ -10,8 +10,14 @@ require "sanitize"
10
10
  require "qiita/markdown/embed/code_pen"
11
11
  require "qiita/markdown/embed/tweet"
12
12
  require "qiita/markdown/embed/asciinema"
13
+ require "qiita/markdown/embed/gist"
14
+ require "qiita/markdown/embed/youtube"
15
+ require "qiita/markdown/embed/slide_share"
16
+ require "qiita/markdown/embed/google_slide"
17
+ require "qiita/markdown/embed/speeker_deck"
13
18
  require "qiita/markdown/transformers/filter_attributes"
14
19
  require "qiita/markdown/transformers/filter_script"
20
+ require "qiita/markdown/transformers/filter_iframe"
15
21
  require "qiita/markdown/transformers/strip_invalid_node"
16
22
  require "qiita/markdown/filters/checkbox"
17
23
  require "qiita/markdown/filters/code_block"
@@ -0,0 +1,9 @@
1
+ module Qiita
2
+ module Markdown
3
+ module Embed
4
+ module Gist
5
+ SCRIPT_HOST = "gist.github.com".freeze
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Qiita
2
+ module Markdown
3
+ module Embed
4
+ module GoogleSlide
5
+ SCRIPT_HOST = "docs.google.com".freeze
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Qiita
2
+ module Markdown
3
+ module Embed
4
+ module SlideShare
5
+ SCRIPT_HOST = "www.slideshare.net".freeze
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module Qiita
2
+ module Markdown
3
+ module Embed
4
+ module SpeekerDeck
5
+ SCRIPT_URLS = [
6
+ "//speakerdeck.com/assets/embed.js",
7
+ ].freeze
8
+ CLASS_NAME = %w[speakerdeck-embed].freeze
9
+ DATA_ATTRIBUTES = %w[
10
+ data-id data-ratio
11
+ ].freeze
12
+ ATTRIBUTES = %w[class] + DATA_ATTRIBUTES
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ module Qiita
2
+ module Markdown
3
+ module Embed
4
+ module Youtube
5
+ SCRIPT_HOSTS = [
6
+ "www.youtube-nocookie.com",
7
+ "www.youtube.com",
8
+ ].freeze
9
+ end
10
+ end
11
+ end
12
+ end
@@ -47,7 +47,9 @@ module Qiita
47
47
  "async",
48
48
  "src",
49
49
  "type",
50
- ],
50
+ ].concat(
51
+ Embed::SpeekerDeck::ATTRIBUTES,
52
+ ),
51
53
  "span" => [
52
54
  "style",
53
55
  ],
@@ -137,6 +139,7 @@ module Qiita
137
139
  "s",
138
140
  "samp",
139
141
  "script",
142
+ "iframe",
140
143
  "span",
141
144
  "strike",
142
145
  "strong",
@@ -186,14 +189,15 @@ module Qiita
186
189
  transformers: [
187
190
  Transformers::StripInvalidNode,
188
191
  Transformers::FilterScript,
192
+ Transformers::FilterIframe,
189
193
  ],
190
194
  }.freeze
191
195
 
192
196
  SCRIPTABLE_RULE = RULE.dup.tap do |rule|
193
197
  rule[:attributes] = RULE[:attributes].dup
194
198
  rule[:attributes][:all] = rule[:attributes][:all] + [:data]
195
- rule[:elements] = RULE[:elements] + ["iframe", "video"]
196
- rule[:transformers] = rule[:transformers] - [Transformers::FilterScript]
199
+ rule[:elements] = RULE[:elements] + ["video"]
200
+ rule[:transformers] = rule[:transformers] - [Transformers::FilterScript, Transformers::FilterIframe]
197
201
  end
198
202
 
199
203
  def call
@@ -6,7 +6,7 @@ module Qiita
6
6
  RULE = {
7
7
  elements: %w[
8
8
  a b blockquote br code dd del details div dl dt em font h1 h2 h3 h4 h5 h6
9
- hr i img ins kbd li ol p pre q rp rt ruby s samp script strike strong sub
9
+ hr i img ins kbd li ol p pre q rp rt ruby s samp script iframe strike strong sub
10
10
  summary sup table tbody td tfoot th thead tr ul var
11
11
  ],
12
12
  attributes: {
@@ -26,7 +26,18 @@ module Qiita
26
26
  "li" => %w[id],
27
27
  "p" => Embed::CodePen::ATTRIBUTES,
28
28
  "q" => %w[cite],
29
- "script" => %w[async src id],
29
+ "script" => %w[async src id].concat(Embed::SpeekerDeck::ATTRIBUTES),
30
+ "iframe" => %w[
31
+ allowfullscreen
32
+ frameborder
33
+ height
34
+ marginheight
35
+ marginwidth
36
+ scrolling
37
+ src
38
+ style
39
+ width
40
+ ],
30
41
  "sup" => %w[id],
31
42
  "td" => %w[colspan rowspan style],
32
43
  "th" => %w[colspan rowspan style],
@@ -42,6 +53,7 @@ module Qiita
42
53
  transformers: [
43
54
  Transformers::FilterAttributes,
44
55
  Transformers::FilterScript,
56
+ Transformers::FilterIframe,
45
57
  ],
46
58
  }.freeze
47
59
 
@@ -0,0 +1,54 @@
1
+ module Qiita
2
+ module Markdown
3
+ module Transformers
4
+ class FilterIframe
5
+ URL_WHITE_LIST = [
6
+ ].flatten.freeze
7
+
8
+ HOST_WHITE_LIST = [
9
+ Embed::Youtube::SCRIPT_HOSTS,
10
+ Embed::SlideShare::SCRIPT_HOST,
11
+ Embed::GoogleSlide::SCRIPT_HOST,
12
+ ].flatten.freeze
13
+
14
+ def self.call(*args)
15
+ new(*args).transform
16
+ end
17
+
18
+ def initialize(env)
19
+ @env = env
20
+ end
21
+
22
+ def transform
23
+ if name == "iframe"
24
+ if URL_WHITE_LIST.include?(node["src"]) || HOST_WHITE_LIST.include?(host_of(node["src"]))
25
+ node["width"] = "100%"
26
+ node.children.unlink
27
+ else
28
+ node.unlink
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def name
36
+ @env[:node_name]
37
+ end
38
+
39
+ def node
40
+ @env[:node]
41
+ end
42
+
43
+ def host_of(url)
44
+ if url
45
+ scheme = URI.parse(url).scheme
46
+ Addressable::URI.parse(url).host if ["http", "https"].include? scheme
47
+ end
48
+ rescue Addressable::URI::InvalidURIError, URI::InvalidURIError
49
+ nil
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -5,10 +5,12 @@ module Qiita
5
5
  URL_WHITE_LIST = [
6
6
  Embed::CodePen::SCRIPT_URLS,
7
7
  Embed::Tweet::SCRIPT_URL,
8
+ Embed::SpeekerDeck::SCRIPT_URLS,
8
9
  ].flatten.freeze
9
10
 
10
11
  HOST_WHITE_LIST = [
11
12
  Embed::Asciinema::SCRIPT_HOST,
13
+ Embed::Gist::SCRIPT_HOST,
12
14
  ].flatten.freeze
13
15
 
14
16
  def self.call(*args)
@@ -41,8 +43,11 @@ module Qiita
41
43
  end
42
44
 
43
45
  def host_of(url)
44
- Addressable::URI.parse(url).host if url
45
- rescue Addressable::URI::InvalidURIError
46
+ if url
47
+ scheme = URI.parse(url).scheme
48
+ Addressable::URI.parse(url).host if ["http", "https"].include? scheme
49
+ end
50
+ rescue Addressable::URI::InvalidURIError, URI::InvalidURIError
46
51
  nil
47
52
  end
48
53
  end
@@ -1,5 +1,5 @@
1
1
  module Qiita
2
2
  module Markdown
3
- VERSION = "0.28.0"
3
+ VERSION = "0.33.0"
4
4
  end
5
5
  end
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "html-pipeline", "~> 2.0"
24
24
  spec.add_dependency "mem"
25
25
  spec.add_dependency "pygments.rb", "~> 1.0"
26
- spec.add_dependency "greenmat", "3.2.2.4"
26
+ spec.add_dependency "greenmat", "3.5.1.1"
27
27
  spec.add_dependency "sanitize"
28
28
  spec.add_dependency "addressable"
29
29
  spec.add_development_dependency "activesupport", "4.2.6"
@@ -740,7 +740,7 @@ describe Qiita::Markdown::Processor do
740
740
 
741
741
  it "generates footnotes elements" do
742
742
  should eq <<-HTML.strip_heredoc
743
- <p><sup id="fnref1"><a href="#fn1" rel="footnote" title="test">1</a></sup></p>
743
+ <p><sup id="fnref1"><a href="#fn1" title="test">1</a></sup></p>
744
744
 
745
745
  <div class="footnotes">
746
746
  <hr>
@@ -756,6 +756,25 @@ describe Qiita::Markdown::Processor do
756
756
  end
757
757
  end
758
758
 
759
+ context "with footenotes syntax with code block" do
760
+ let(:markdown) do
761
+ <<-MARKDOWN.strip_heredoc
762
+ ```
763
+ [^1]
764
+ [^1]: test
765
+ ```
766
+ MARKDOWN
767
+ end
768
+
769
+ it "generates only code blocks without footnotes" do
770
+ should eq <<-HTML.strip_heredoc
771
+ <div class="code-frame" data-lang="text"><div class="highlight"><pre><span></span>[^1]
772
+ [^1]: test
773
+ </pre></div></div>
774
+ HTML
775
+ end
776
+ end
777
+
759
778
  context "with manually written link inside of <sup> tag" do
760
779
  let(:markdown) do
761
780
  <<-MARKDOWN.strip_heredoc
@@ -1031,6 +1050,31 @@ describe Qiita::Markdown::Processor do
1031
1050
  end
1032
1051
  end
1033
1052
  end
1053
+
1054
+ context "with details tag" do
1055
+ let(:markdown) do
1056
+ <<-MARKDOWN.strip_heredoc
1057
+ <details><summary>Folding sample</summary><div>
1058
+
1059
+ ```rb
1060
+ puts "Hello, World"
1061
+ ```
1062
+ </div></details>
1063
+ MARKDOWN
1064
+ end
1065
+
1066
+ it "returns HTML output parsed as markdown" do
1067
+ expect(subject).to eq <<-HTML.strip_heredoc
1068
+ <p><details><summary>Folding sample</summary><div>
1069
+
1070
+ <div class="code-frame" data-lang="rb"><div class="highlight"><pre><span></span><span class="nb">puts</span> <span class="s2">"Hello, World"</span>
1071
+ </pre></div></div>
1072
+
1073
+ <p></p>
1074
+ </div></details></p>
1075
+ HTML
1076
+ end
1077
+ end
1034
1078
  end
1035
1079
 
1036
1080
  shared_examples_for "script element" do |allowed:|
@@ -1407,6 +1451,138 @@ describe Qiita::Markdown::Processor do
1407
1451
  end
1408
1452
  end
1409
1453
 
1454
+ context "with HTML embed code for Gist" do
1455
+ let(:markdown) do
1456
+ <<-MARKDOWN.strip_heredoc
1457
+ <script id="example" src="https://gist.github.com/a/example.js"></script>
1458
+ MARKDOWN
1459
+ end
1460
+
1461
+ if allowed
1462
+ it "does not sanitize embed code" do
1463
+ should eq <<-HTML.strip_heredoc
1464
+ <script id="example" src="https://gist.github.com/a/example.js"></script>
1465
+ HTML
1466
+ end
1467
+ else
1468
+ it "forces async attribute on script" do
1469
+ should eq <<-HTML.strip_heredoc
1470
+ <script id="example" src="https://gist.github.com/a/example.js" async="async"></script>
1471
+ HTML
1472
+ end
1473
+ end
1474
+ end
1475
+
1476
+ context "with HTML embed code for Youtube" do
1477
+ let(:markdown) do
1478
+ <<-MARKDOWN.strip_heredoc
1479
+ <iframe width="100" height="100" src="https://www.youtube.com/embed/example"></iframe>
1480
+ MARKDOWN
1481
+ end
1482
+
1483
+ if allowed
1484
+ it "does not sanitize embed code" do
1485
+ should eq <<-HTML.strip_heredoc
1486
+ <iframe width="100" height="100" src="https://www.youtube.com/embed/example"></iframe>
1487
+ HTML
1488
+ end
1489
+ else
1490
+ it "forces width attribute on iframe" do
1491
+ should eq <<-HTML.strip_heredoc
1492
+ <iframe width="100%" height="100" src="https://www.youtube.com/embed/example"></iframe>
1493
+ HTML
1494
+ end
1495
+ end
1496
+
1497
+ context "when url is privacy enhanced mode" do
1498
+ let(:markdown) do
1499
+ <<-MARKDOWN.strip_heredoc
1500
+ <iframe width="100" height="100" src="https://www.youtube-nocookie.com/embed/example"></iframe>
1501
+ MARKDOWN
1502
+ end
1503
+
1504
+ if allowed
1505
+ it "does not sanitize embed code" do
1506
+ should eq <<-HTML.strip_heredoc
1507
+ <iframe width="100" height="100" src="https://www.youtube-nocookie.com/embed/example"></iframe>
1508
+ HTML
1509
+ end
1510
+ else
1511
+ it "forces width attribute on iframe" do
1512
+ should eq <<-HTML.strip_heredoc
1513
+ <iframe width="100%" height="100" src="https://www.youtube-nocookie.com/embed/example"></iframe>
1514
+ HTML
1515
+ end
1516
+ end
1517
+ end
1518
+ end
1519
+
1520
+ context "with HTML embed code for SlideShare" do
1521
+ let(:markdown) do
1522
+ <<-MARKDOWN.strip_heredoc
1523
+ <iframe width="100" height="100" src="https://www.slideshare.net/embed/example"></iframe>
1524
+ MARKDOWN
1525
+ end
1526
+
1527
+ if allowed
1528
+ it "does not sanitize embed code" do
1529
+ should eq <<-HTML.strip_heredoc
1530
+ <iframe width="100" height="100" src="https://www.slideshare.net/embed/example"></iframe>
1531
+ HTML
1532
+ end
1533
+ else
1534
+ it "forces width attribute on iframe" do
1535
+ should eq <<-HTML.strip_heredoc
1536
+ <iframe width="100%" height="100" src="https://www.slideshare.net/embed/example"></iframe>
1537
+ HTML
1538
+ end
1539
+ end
1540
+ end
1541
+
1542
+ context "with HTML embed code for GoogleSlide" do
1543
+ let(:markdown) do
1544
+ <<-MARKDOWN.strip_heredoc
1545
+ <iframe src="https://docs.google.com/presentation/d/example/embed" frameborder="0" width="482" height="300" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
1546
+ MARKDOWN
1547
+ end
1548
+
1549
+ if allowed
1550
+ it "does not sanitize embed code" do
1551
+ should eq <<-HTML.strip_heredoc
1552
+ <iframe src="https://docs.google.com/presentation/d/example/embed" frameborder="0" width="482" height="300" allowfullscreen="true"></iframe>
1553
+ HTML
1554
+ end
1555
+ else
1556
+ it "forces width attribute on iframe" do
1557
+ should eq <<-HTML.strip_heredoc
1558
+ <iframe src="https://docs.google.com/presentation/d/example/embed" frameborder="0" width="100%" height="300" allowfullscreen="true"></iframe>
1559
+ HTML
1560
+ end
1561
+ end
1562
+ end
1563
+
1564
+ context "with HTML embed code for SpeekerDeck" do
1565
+ let(:markdown) do
1566
+ <<-MARKDOWN.strip_heredoc
1567
+ <script async class="speakerdeck-embed" data-id="example" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
1568
+ MARKDOWN
1569
+ end
1570
+
1571
+ if allowed
1572
+ it "does not sanitize embed code" do
1573
+ should eq <<-HTML.strip_heredoc
1574
+ <script async class="speakerdeck-embed" data-id="example" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
1575
+ HTML
1576
+ end
1577
+ else
1578
+ it "forces async attribute on script" do
1579
+ should eq <<-HTML.strip_heredoc
1580
+ <script async class="speakerdeck-embed" data-id="example" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
1581
+ HTML
1582
+ end
1583
+ end
1584
+ end
1585
+
1410
1586
  context "with embed code for Tweet" do
1411
1587
  let(:markdown) do
1412
1588
  <<-MARKDOWN.strip_heredoc
@@ -1422,6 +1598,34 @@ describe Qiita::Markdown::Processor do
1422
1598
  HTML
1423
1599
  end
1424
1600
  end
1601
+
1602
+ context "with embed script code with xss" do
1603
+ let(:markdown) do
1604
+ <<-MARKDOWN.strip_heredoc
1605
+ <script async class="speakerdeck-embed" data-id="example" data-ratio="1.33333333333333" src="javascript://speakerdeck.com/assets/embed.js"></script>
1606
+ MARKDOWN
1607
+
1608
+ it "forces width attribute on iframe" do
1609
+ should eq <<-HTML.strip_heredoc
1610
+ \n
1611
+ HTML
1612
+ end
1613
+ end
1614
+ end
1615
+
1616
+ context "with embed iframe code with xss" do
1617
+ let(:markdown) do
1618
+ <<-MARKDOWN.strip_heredoc
1619
+ <iframe src="javascript://docs.google.com:80/%0d%0aalert(document.domain)" frameborder="0" width="482" height="300" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
1620
+ MARKDOWN
1621
+
1622
+ it "forces width attribute on iframe" do
1623
+ should eq <<-HTML.strip_heredoc
1624
+ \n
1625
+ HTML
1626
+ end
1627
+ end
1628
+ end
1425
1629
  end
1426
1630
 
1427
1631
  context "without script and strict context" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qiita-markdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.28.0
4
+ version: 0.33.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-21 00:00:00.000000000 Z
11
+ date: 2021-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gemoji
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 3.2.2.4
89
+ version: 3.5.1.1
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 3.2.2.4
96
+ version: 3.5.1.1
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: sanitize
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -258,7 +258,12 @@ files:
258
258
  - lib/qiita/markdown/base_processor.rb
259
259
  - lib/qiita/markdown/embed/asciinema.rb
260
260
  - lib/qiita/markdown/embed/code_pen.rb
261
+ - lib/qiita/markdown/embed/gist.rb
262
+ - lib/qiita/markdown/embed/google_slide.rb
263
+ - lib/qiita/markdown/embed/slide_share.rb
264
+ - lib/qiita/markdown/embed/speeker_deck.rb
261
265
  - lib/qiita/markdown/embed/tweet.rb
266
+ - lib/qiita/markdown/embed/youtube.rb
262
267
  - lib/qiita/markdown/filters/checkbox.rb
263
268
  - lib/qiita/markdown/filters/code_block.rb
264
269
  - lib/qiita/markdown/filters/emoji.rb
@@ -281,6 +286,7 @@ files:
281
286
  - lib/qiita/markdown/processor.rb
282
287
  - lib/qiita/markdown/summary_processor.rb
283
288
  - lib/qiita/markdown/transformers/filter_attributes.rb
289
+ - lib/qiita/markdown/transformers/filter_iframe.rb
284
290
  - lib/qiita/markdown/transformers/filter_script.rb
285
291
  - lib/qiita/markdown/transformers/strip_invalid_node.rb
286
292
  - lib/qiita/markdown/version.rb