angular_xss 0.4.0 → 1.0.0

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +19 -9
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +20 -1
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +1 -1
  7. data/{Gemfile.rails-3.2 → Gemfile.rails-3.2.haml-4} +1 -1
  8. data/{Gemfile.rails-3.2.lock → Gemfile.rails-3.2.haml-4.lock} +4 -4
  9. data/Gemfile.rails-4.2.haml-4 +1 -1
  10. data/Gemfile.rails-4.2.haml-4.lock +4 -4
  11. data/Gemfile.rails-4.2.haml-5 +1 -1
  12. data/Gemfile.rails-4.2.haml-5.lock +4 -4
  13. data/Gemfile.rails-5.1.haml-4 +1 -1
  14. data/Gemfile.rails-5.1.haml-4.lock +8 -6
  15. data/Gemfile.rails-5.1.haml-5 +1 -1
  16. data/Gemfile.rails-5.1.haml-5.lock +9 -7
  17. data/Gemfile.rails-6.1.haml-5 +1 -1
  18. data/Gemfile.rails-6.1.haml-5.lock +3 -3
  19. data/Gemfile.rails-7.0.haml-5 +8 -0
  20. data/Gemfile.rails-7.0.haml-5.lock +88 -0
  21. data/Gemfile.rails-7.1.haml-5 +9 -0
  22. data/Gemfile.rails-7.1.haml-5.lock +105 -0
  23. data/Gemfile.rails-7.1.haml-6 +9 -0
  24. data/Gemfile.rails-7.1.haml-6.lock +122 -0
  25. data/README.md +11 -2
  26. data/angular_xss.gemspec +1 -0
  27. data/lib/angular_xss/erb.rb +17 -27
  28. data/lib/angular_xss/escaper.rb +8 -0
  29. data/lib/angular_xss/haml.rb +25 -19
  30. data/lib/angular_xss/output_buffer.rb +25 -0
  31. data/lib/angular_xss/safe_buffer.rb +31 -7
  32. data/lib/angular_xss/version.rb +1 -1
  33. data/lib/angular_xss.rb +1 -0
  34. data/spec/angular_xss/erb_spec.rb +46 -3
  35. data/spec/angular_xss/escaper_spec.rb +21 -0
  36. data/spec/angular_xss/haml_spec.rb +0 -2
  37. data/spec/angular_xss/output_buffer_spec.rb +45 -0
  38. data/spec/angular_xss/safe_buffer_spec.rb +16 -4
  39. data/spec/spec_helper.rb +5 -11
  40. data/spec/support/engine_preventing_angular_xss.rb +21 -17
  41. data/spec/templates/_test_erb.erb +14 -5
  42. data/spec/templates/_test_haml.haml +40 -23
  43. metadata +18 -6
@@ -0,0 +1,122 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ angular_xss (1.0.0)
5
+ activesupport
6
+ haml (>= 3.1.5)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ actionpack (7.1.3.4)
12
+ actionview (= 7.1.3.4)
13
+ activesupport (= 7.1.3.4)
14
+ nokogiri (>= 1.8.5)
15
+ racc
16
+ rack (>= 2.2.4)
17
+ rack-session (>= 1.0.1)
18
+ rack-test (>= 0.6.3)
19
+ rails-dom-testing (~> 2.2)
20
+ rails-html-sanitizer (~> 1.6)
21
+ actionview (7.1.3.4)
22
+ activesupport (= 7.1.3.4)
23
+ builder (~> 3.1)
24
+ erubi (~> 1.11)
25
+ rails-dom-testing (~> 2.2)
26
+ rails-html-sanitizer (~> 1.6)
27
+ activesupport (7.1.3.4)
28
+ base64
29
+ bigdecimal
30
+ concurrent-ruby (~> 1.0, >= 1.0.2)
31
+ connection_pool (>= 2.2.5)
32
+ drb
33
+ i18n (>= 1.6, < 2)
34
+ minitest (>= 5.1)
35
+ mutex_m
36
+ tzinfo (~> 2.0)
37
+ base64 (0.2.0)
38
+ bigdecimal (3.1.8)
39
+ builder (3.3.0)
40
+ byebug (11.1.3)
41
+ concurrent-ruby (1.3.3)
42
+ connection_pool (2.4.1)
43
+ crass (1.0.6)
44
+ diff-lcs (1.5.1)
45
+ drb (2.2.1)
46
+ erubi (1.13.0)
47
+ gemika (0.8.3)
48
+ haml (6.3.0)
49
+ temple (>= 0.8.2)
50
+ thor
51
+ tilt
52
+ i18n (1.14.5)
53
+ concurrent-ruby (~> 1.0)
54
+ loofah (2.22.0)
55
+ crass (~> 1.0.2)
56
+ nokogiri (>= 1.12.0)
57
+ minitest (5.24.0)
58
+ mutex_m (0.2.0)
59
+ nokogiri (1.16.6-aarch64-linux)
60
+ racc (~> 1.4)
61
+ nokogiri (1.16.6-arm-linux)
62
+ racc (~> 1.4)
63
+ nokogiri (1.16.6-arm64-darwin)
64
+ racc (~> 1.4)
65
+ nokogiri (1.16.6-x86-linux)
66
+ racc (~> 1.4)
67
+ nokogiri (1.16.6-x86_64-darwin)
68
+ racc (~> 1.4)
69
+ nokogiri (1.16.6-x86_64-linux)
70
+ racc (~> 1.4)
71
+ racc (1.8.0)
72
+ rack (3.1.3)
73
+ rack-session (2.0.0)
74
+ rack (>= 3.0.0)
75
+ rack-test (2.1.0)
76
+ rack (>= 1.3)
77
+ rails-dom-testing (2.2.0)
78
+ activesupport (>= 5.0.0)
79
+ minitest
80
+ nokogiri (>= 1.6)
81
+ rails-html-sanitizer (1.6.0)
82
+ loofah (~> 2.21)
83
+ nokogiri (~> 1.14)
84
+ rake (13.2.1)
85
+ rspec (3.13.0)
86
+ rspec-core (~> 3.13.0)
87
+ rspec-expectations (~> 3.13.0)
88
+ rspec-mocks (~> 3.13.0)
89
+ rspec-core (3.13.0)
90
+ rspec-support (~> 3.13.0)
91
+ rspec-expectations (3.13.1)
92
+ diff-lcs (>= 1.2.0, < 2.0)
93
+ rspec-support (~> 3.13.0)
94
+ rspec-mocks (3.13.1)
95
+ diff-lcs (>= 1.2.0, < 2.0)
96
+ rspec-support (~> 3.13.0)
97
+ rspec-support (3.13.1)
98
+ temple (0.10.3)
99
+ thor (1.3.1)
100
+ tilt (2.3.0)
101
+ tzinfo (2.0.6)
102
+ concurrent-ruby (~> 1.0)
103
+
104
+ PLATFORMS
105
+ aarch64-linux
106
+ arm-linux
107
+ arm64-darwin
108
+ x86-linux
109
+ x86_64-darwin
110
+ x86_64-linux
111
+
112
+ DEPENDENCIES
113
+ actionpack (~> 7.1)
114
+ angular_xss!
115
+ byebug
116
+ gemika (>= 0.8.3)
117
+ haml (~> 6)
118
+ rake
119
+ rspec
120
+
121
+ BUNDLED WITH
122
+ 2.5.13
data/README.md CHANGED
@@ -7,6 +7,12 @@ This gem patches ERB/rails_xss and Haml so Angular interpolation symbols are aut
7
7
 
8
8
  **This is an unsatisfactory hack.** A better solution is very much desired, but is not possible without some changes in AngularJS. See the [related AngularJS issue](https://github.com/angular/angular.js/issues/5601).
9
9
 
10
+ 🚧 Notice: unmaintained gem
11
+ ------------------
12
+
13
+ We are no longer actively maintaining this gem.
14
+
15
+ The `1.0` release added support for HAML 6 and Rails 7.1, so the gem will at least support Rails 3.2 - 7.1 and HAML 4 - 6. `angular_xss` might still work for future versions HAML and Rails, but we won't actively ensure it does.
10
16
 
11
17
  Disable escaping locally
12
18
  ------------------------
@@ -56,10 +62,13 @@ Development
56
62
  -----------
57
63
 
58
64
  - Fork the repository.
59
- - Push your changes with specs. There is a Rails 3 test application in `spec/app_root` if you need to test integration with a live Rails app.
65
+ - Prepare your changes, and ensure existing and new test are green:
66
+ - `bundle exec rake matrix:install` installs all dependencies for all Gemfiles
67
+ - `bundle exec rake matrix:spec` runs all specs in all configurations
68
+ - You may run single tests with a specified Rails version via `BUNDLE_GEMFILE=Gemfile.rails-7.0.haml-5 bundle exec rspec ./spec/angular_xss`
69
+ - Push your changes with specs. There is a test application in `spec/app_root` if you need to test integration with a live Rails app.
60
70
  - Send a pull request.
61
71
 
62
-
63
72
  Credits
64
73
  -------
65
74
 
data/angular_xss.gemspec CHANGED
@@ -10,6 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.summary = 'Patches rails_xss and Haml so AngularJS interpolations are auto-escaped in unsafe strings.'
11
11
  s.description = s.summary
12
12
  s.license = 'MIT'
13
+ s.metadata = { 'rubygems_mfa_required' => 'true' }
13
14
 
14
15
  s.files = `git ls-files`.split($\)
15
16
  s.test_files = s.files.grep(%r{^spec/})
@@ -1,33 +1,25 @@
1
- # Use module_eval so we crash when ERB::Util has not yet been loaded.
2
- ERB::Util.module_eval do
3
-
4
- if private_method_defined? :unwrapped_html_escape # Rails 4.2+
5
-
6
- def unwrapped_html_escape_with_escaping_angular_expressions(s)
7
- s = s.to_s
8
- if s.html_safe?
9
- s
10
- else
11
- unwrapped_html_escape_without_escaping_angular_expressions(AngularXss::Escaper.escape(s))
12
- end
1
+ if ERB::Util.private_method_defined? :unwrapped_html_escape
2
+ # Rails 4.2+
3
+ # https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/erb/util.rb
4
+ module ERBUtilExt
5
+ def html_escape_once(s)
6
+ super(AngularXss::Escaper.escape_if_unsafe(s))
13
7
  end
14
8
 
15
- alias_method :unwrapped_html_escape_without_escaping_angular_expressions, :unwrapped_html_escape
16
- alias_method :unwrapped_html_escape, :unwrapped_html_escape_with_escaping_angular_expressions
17
-
18
- singleton_class.send(:remove_method, :unwrapped_html_escape)
19
- module_function :unwrapped_html_escape
20
- module_function :unwrapped_html_escape_without_escaping_angular_expressions
9
+ def unwrapped_html_escape(s)
10
+ super(AngularXss::Escaper.escape_if_unsafe(s))
11
+ end
12
+ # Note that html_escape() and h() are passively fixed as they are calling the two methods above
13
+ end
14
+ ERB::Util.prepend ERBUtilExt
15
+ ERB::Util.singleton_class.prepend ERBUtilExt
21
16
 
22
- else # Rails < 4.2
17
+ else
18
+ ERB::Util.module_eval do
19
+ # Rails < 4.2
23
20
 
24
21
  def html_escape_with_escaping_angular_expressions(s)
25
- s = s.to_s
26
- if s.html_safe?
27
- s
28
- else
29
- html_escape_without_escaping_angular_expressions(AngularXss::Escaper.escape(s))
30
- end
22
+ html_escape_without_escaping_angular_expressions(AngularXss::Escaper.escape_if_unsafe(s))
31
23
  end
32
24
 
33
25
  alias_method_chain :html_escape, :escaping_angular_expressions
@@ -41,7 +33,5 @@ ERB::Util.module_eval do
41
33
  singleton_class.send(:remove_method, :html_escape)
42
34
  module_function :html_escape
43
35
  module_function :html_escape_without_escaping_angular_expressions
44
-
45
36
  end
46
-
47
37
  end
@@ -27,6 +27,14 @@ module AngularXss
27
27
  end
28
28
  end
29
29
 
30
+ def self.escape_if_unsafe(string)
31
+ if string.nil? || string.to_s.html_safe?
32
+ string
33
+ else
34
+ escape(string.to_s)
35
+ end
36
+ end
37
+
30
38
  def self.disabled?
31
39
  !!Thread.current[XSS_DISABLED_KEY]
32
40
  end
@@ -1,32 +1,38 @@
1
- # Haml 5.0 and 5.1 fall back to erb
2
- if Haml::VERSION < '5'
1
+ haml_version = Gem::Version.new(Haml::VERSION)
2
+
3
+ if haml_version < Gem::Version.new(5)
3
4
  # Use module_eval so we crash when Haml::Helpers has not yet been loaded.
4
5
  Haml::Helpers.module_eval do
5
-
6
6
  def html_escape_with_escaping_angular_expressions(s)
7
- s = s.to_s
8
- if s.html_safe?
9
- s
10
- else
11
- html_escape_without_escaping_angular_expressions(AngularXss::Escaper.escape(s))
12
- end
7
+ html_escape_without_escaping_angular_expressions(AngularXss::Escaper.escape_if_unsafe(s))
13
8
  end
14
9
 
15
10
  alias_method :html_escape_without_escaping_angular_expressions, :html_escape
16
11
  alias_method :html_escape, :html_escape_with_escaping_angular_expressions
17
12
  end
13
+ elsif haml_version < Gem::Version.new('5.2')
14
+ # Haml 5.0 and 5.1 fall back to erb
15
+ elsif haml_version < Gem::Version.new(6)
16
+ # HAML 5.2+
17
+ module HTMLEscapeWithoutHAMLWithAngularXSS
18
+ def html_escape_without_haml_xss(html)
19
+ super(AngularXss::Escaper.escape_if_unsafe(html))
20
+ end
21
+ end
18
22
 
19
- elsif Haml::VERSION >= '5.2'
20
- Haml::Helpers.module_eval do
21
-
22
- def html_escape_without_haml_xss_with_escaping_angular_expressions(s)
23
- s = s.to_s
24
- return s if s.html_safe?
23
+ Haml::Helpers.singleton_class.prepend HTMLEscapeWithoutHAMLWithAngularXSS
24
+ else
25
+ # Haml 6+
26
+ # It ditched most of is own helpers in favor of Haml::Util.escape_html
27
+ # https://github.com/haml/haml/blob/main/CHANGELOG.md#600
28
+ # https://github.com/haml/haml/compare/v5.2.2...v6.3.0
29
+ # https://github.com/haml/haml/blob/v6.3.0/lib/haml/util.rb
25
30
 
26
- html_escape_without_haml_xss_without_escaping_angular_expressions(AngularXss::Escaper.escape(s))
31
+ module EscapeHTMLWithAngularXSS
32
+ def escape_html(html)
33
+ super(AngularXss::Escaper.escape_if_unsafe(html))
27
34
  end
28
-
29
- alias_method :html_escape_without_haml_xss_without_escaping_angular_expressions, :html_escape_without_haml_xss
30
- alias_method :html_escape_without_haml_xss, :html_escape_without_haml_xss_with_escaping_angular_expressions
31
35
  end
36
+
37
+ Haml::Util.singleton_class.prepend EscapeHTMLWithAngularXSS
32
38
  end
@@ -0,0 +1,25 @@
1
+ ##
2
+ # Monkey patch ActionView::OutputBuffer to escape double braces from Angular
3
+ #
4
+ # Link to the original implementation without Angular XSS escaping:
5
+ # https://github.com/rails/rails/blob/v7.1.3.4/actionview/lib/action_view/buffers.rb
6
+
7
+
8
+ if defined?(ActionView::VERSION) && Gem::Version.new(ActionView::VERSION::STRING) >= Gem::Version.new('7.1')
9
+ # ActionView < 7.1 used our patched ERB::Util.h to escape, 7.1 switched to CGI.escapeHTML
10
+ module OutputBufferWithEscapedAngularXSS
11
+ def <<(value)
12
+ super(AngularXss::Escaper.escape_if_unsafe(value))
13
+ end
14
+
15
+ def concat(value)
16
+ super(AngularXss::Escaper.escape_if_unsafe(value))
17
+ end
18
+
19
+ def append=(value)
20
+ super(AngularXss::Escaper.escape_if_unsafe(value))
21
+ end
22
+ end
23
+
24
+ ActionView::OutputBuffer.prepend OutputBufferWithEscapedAngularXSS
25
+ end
@@ -1,20 +1,44 @@
1
+ ##
2
+ # Monkey patch ActiveSupport::SafeBuffer to escape double braces from Angular
3
+ #
4
+ # Link to the original implementation without Angular XSS escaping:
5
+ # https://github.com/rails/rails/blob/7-0-stable/activesupport/lib/active_support/core_ext/string/output_safety.rb#L295
6
+ #
1
7
  ActiveSupport::SafeBuffer.class_eval do
2
8
 
3
- if private_method_defined? :html_escape_interpolated_argument
9
+ html_escape = :html_escape_interpolated_argument
10
+
11
+ if private_method_defined?(html_escape) || # Rails < 6.1
12
+ private_method_defined?(:"explicit_#{html_escape}") # Rails >= 6.1
4
13
 
5
14
  private
6
15
 
7
- def html_escape_interpolated_argument_with_angular_xss(arg)
8
- if arg.html_safe?
16
+ def explicit_html_escape_interpolated_argument_with_angular_xss(arg)
17
+ if !html_safe? || arg.html_safe?
9
18
  arg
10
19
  else
11
- html_escape_interpolated_argument_without_angular_xss(AngularXss::Escaper.escape(arg))
20
+ explicit_html_escape_interpolated_argument_without_angular_xss(AngularXss::Escaper.escape(arg))
12
21
  end
13
22
  end
14
23
 
15
- alias_method :html_escape_interpolated_argument_without_angular_xss, :html_escape_interpolated_argument
16
- alias_method :html_escape_interpolated_argument, :html_escape_interpolated_argument_with_angular_xss
24
+ if private_method_defined?(html_escape)
25
+ alias_method :"explicit_#{html_escape}_without_angular_xss", html_escape
26
+ alias_method html_escape, :"explicit_#{html_escape}_with_angular_xss"
27
+ elsif private_method_defined?(:"explicit_#{html_escape}")
28
+ alias_method :"explicit_#{html_escape}_without_angular_xss", :"explicit_#{html_escape}"
29
+ alias_method :"explicit_#{html_escape}", :"explicit_#{html_escape}_with_angular_xss"
30
+ end
17
31
 
32
+ if private_method_defined?(:"implicit_#{html_escape}")
33
+ def implicit_html_escape_interpolated_argument_with_angular_xss(arg)
34
+ if !html_safe? || arg.html_safe?
35
+ arg
36
+ else
37
+ implicit_html_escape_interpolated_argument_without_angular_xss(AngularXss::Escaper.escape(arg))
38
+ end
39
+ end
40
+ alias_method :"implicit_#{html_escape}_without_angular_xss", :"implicit_#{html_escape}"
41
+ alias_method :"implicit_#{html_escape}", :"implicit_#{html_escape}_with_angular_xss"
42
+ end
18
43
  end
19
-
20
44
  end
@@ -1,3 +1,3 @@
1
1
  module AngularXss
2
- VERSION = '0.4.0'
2
+ VERSION = '1.0.0'
3
3
  end
data/lib/angular_xss.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  #"string".respond_to?(:html_safe?) or raise "No rails_xss implementation present"
2
2
 
3
3
  require 'angular_xss/escaper'
4
+ require 'angular_xss/output_buffer'
4
5
  require 'angular_xss/safe_buffer'
5
6
  require 'angular_xss/erb'
6
7
  require 'angular_xss/haml'
@@ -1,7 +1,50 @@
1
- require 'spec_helper'
2
-
3
1
  describe 'Angular XSS prevention in ERB', :type => :view do
4
-
5
2
  it_should_behave_like 'engine preventing Angular XSS', :partial => 'test_erb'
3
+ end
4
+
5
+ describe ERB::Util do
6
+ describe '#html_escape' do
7
+ it 'escapes angular braces' do
8
+ expect(described_class.html_escape("{{unsafe}}")).to eq("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
9
+ end
10
+
11
+ it 'does not modify already HTML safe strings' do
12
+ expect(described_class.html_escape("{{safe}}".html_safe)).to eq("{{safe}}")
13
+ end
14
+ end
15
+
16
+ describe '#h' do
17
+ it 'escapes angular braces' do
18
+ expect(described_class.h("{{unsafe}}")).to eq("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
19
+ end
20
+
21
+ it 'does not modify already HTML safe strings' do
22
+ expect(described_class.h("{{safe}}".html_safe)).to eq("{{safe}}")
23
+ end
24
+ end
25
+
26
+ # Rails < 4 does not implement unwrapped_html_escape and html_escape_once
27
+ if described_class.method_defined? :unwrapped_html_escape
28
+ describe '#unwrapped_html_escape' do
29
+ it 'escapes angular braces' do
30
+ expect(described_class.unwrapped_html_escape("{{unsafe}}")).to eq("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
31
+ end
32
+
33
+ it 'does not modify already HTML safe strings' do
34
+ expect(described_class.unwrapped_html_escape("{{safe}}".html_safe)).to eq("{{safe}}")
35
+ end
36
+ end
37
+ end
38
+
39
+ if described_class.method_defined? :html_escape_once
40
+ describe '#html_escape_once' do
41
+ it 'escapes angular braces' do
42
+ expect(described_class.html_escape_once("{{unsafe}}")).to eq("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
43
+ end
6
44
 
45
+ it 'does not modify already HTML safe strings' do
46
+ expect(described_class.html_escape_once("{{safe}}".html_safe)).to eq("{{safe}}")
47
+ end
48
+ end
49
+ end
7
50
  end
@@ -0,0 +1,21 @@
1
+ describe AngularXss::Escaper do
2
+ describe '.escape' do
3
+ it 'replaces double braces with a closed variant' do
4
+ expect(described_class.escape('{{')).to eq('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}')
5
+ end
6
+
7
+ it 'does not handle HTML safe strings differently' do
8
+ expect(described_class.escape('{{'.html_safe)).to eq('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}')
9
+ end
10
+ end
11
+
12
+ describe '.escape_if_unsafe' do
13
+ it 'replaces double braces with a closed variant' do
14
+ expect(described_class.escape_if_unsafe('{{')).to eq('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}')
15
+ end
16
+
17
+ it 'does not modify HTML safe strings' do
18
+ expect(described_class.escape_if_unsafe('{{'.html_safe)).to eq('{{')
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe 'Angular XSS prevention in Haml', :type => :view do
4
2
 
5
3
  it_should_behave_like 'engine preventing Angular XSS', :partial => 'test_haml'
@@ -0,0 +1,45 @@
1
+ describe ActionView::OutputBuffer do
2
+ describe '#<<' do
3
+ it 'escapes angular braces' do
4
+ expect((subject << "{{unsafe}}").to_s).to eq("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
5
+ end
6
+
7
+ it 'does not change behavior for already HTML safe strings' do
8
+ expect((subject << "{{safe}}".html_safe).to_s).to eq("{{safe}}")
9
+ end
10
+
11
+ it 'allows concatting nil' do
12
+ expect { subject << nil }.to_not raise_error
13
+ end
14
+ end
15
+
16
+ describe '#concat' do
17
+ it 'escapes angular braces' do
18
+ expect((subject.concat "{{unsafe}}").to_s).to eq("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
19
+ end
20
+
21
+ it 'does not change behavior for already HTML safe strings' do
22
+ expect((subject.concat "{{safe}}".html_safe).to_s).to eq("{{safe}}")
23
+ end
24
+
25
+ it 'allows concatting nil' do
26
+ expect { subject.concat nil }.to_not raise_error
27
+ end
28
+ end
29
+
30
+ describe '#append=' do
31
+ it 'escapes angular braces' do
32
+ subject.append = "{{unsafe}}"
33
+ expect(subject.to_s).to eq("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
34
+ end
35
+
36
+ it 'does not change behavior for already HTML safe strings' do
37
+ subject.append = "{{safe}}".html_safe
38
+ expect(subject.to_s).to eq("{{safe}}")
39
+ end
40
+
41
+ it 'allows concatting nil' do
42
+ expect { subject.append = nil }.to_not raise_error
43
+ end
44
+ end
45
+ end
@@ -1,9 +1,21 @@
1
- require 'spec_helper'
2
-
3
1
  describe ActiveSupport::SafeBuffer do
4
2
 
5
- it 'still allows concatting nil' do
6
- expect { subject << nil }.to_not raise_error
3
+ describe '#<<' do
4
+ it 'escapes angular braces' do
5
+ subject << "{{unsafe}}"
6
+ expect(subject.to_s).to eq("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
7
+ end
8
+
9
+ it 'allows concatting nil' do
10
+ expect { subject << nil }.to_not raise_error
11
+ end
12
+ end
13
+
14
+ describe '#+' do
15
+ it 'escapes angular braces' do
16
+ combined_string = subject + "{{unsafe}}"
17
+ expect(combined_string.to_s).to eq("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
18
+ end
7
19
  end
8
20
 
9
21
  end
data/spec/spec_helper.rb CHANGED
@@ -17,7 +17,11 @@ module Rails
17
17
  end
18
18
 
19
19
  require 'haml'
20
- require 'haml/template'
20
+ if Gem::Version.new(Haml::VERSION) < Gem::Version.new(6)
21
+ require 'haml/template'
22
+ else
23
+ require 'haml/rails_template'
24
+ end
21
25
 
22
26
  require 'angular_xss'
23
27
 
@@ -25,13 +29,3 @@ require 'angular_xss'
25
29
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
26
30
 
27
31
  TEMPLATE_ROOT = Pathname.new(__dir__).join('templates')
28
-
29
-
30
- RSpec.configure do |config|
31
- config.mock_with :rspec do |c|
32
- c.syntax = [:should, :expect]
33
- end
34
- config.expect_with :rspec do |c|
35
- c.syntax = [:should, :expect]
36
- end
37
- end
@@ -2,7 +2,7 @@ shared_examples_for 'engine preventing Angular XSS' do |partial:|
2
2
 
3
3
  let(:path_set) { ActionView::LookupContext.new([TEMPLATE_ROOT]) }
4
4
 
5
- if defined?(ActionView::VERSION) && ActionView::VERSION::MAJOR >= 6
5
+ if defined?(ActionView::VERSION) && Gem::Version.new(ActionView::VERSION::MAJOR) >= Gem::Version.new(6)
6
6
  let(:engine) { ActionView::Base.with_empty_template_cache.new(path_set, {}, nil) }
7
7
  else
8
8
  let(:engine) { ActionView::Base.new(path_set) }
@@ -11,14 +11,18 @@ shared_examples_for 'engine preventing Angular XSS' do |partial:|
11
11
  let(:html) { engine.render(partial) }
12
12
 
13
13
  it 'escapes Angular interpolation marks in unsafe strings' do
14
- html.should_not include('{{unsafe}}')
15
- html.should include('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}')
14
+ expect(html).not_to include('{{unsafe}}')
15
+ expect(html).to include('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}')
16
16
  end
17
17
 
18
18
  it 'recognizes the many ways to express an opening curly brace in HTML' do
19
+ # Only unsafe strings are escaped
20
+ expect(html).to include("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
21
+ expect(html).not_to include("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}safe}}")
19
22
 
20
- html.should include("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}")
21
- html.should_not include("{{unsafe}}")
23
+ # Only safe strings with braces are left untouched
24
+ expect(html).to include("{{safe}}")
25
+ expect(html).not_to include("{{unsafe}}")
22
26
 
23
27
  braces = [
24
28
  '{',
@@ -35,15 +39,15 @@ shared_examples_for 'engine preventing Angular XSS' do |partial:|
35
39
 
36
40
  braces.each do |brace1|
37
41
  braces.each do |brace2|
38
- html.should_not include("#{brace1}#{brace2}unsafe}}")
42
+ expect(html).not_to include("#{brace1}#{brace2}unsafe}}")
39
43
  end
40
44
  end
41
45
 
42
46
  end
43
47
 
44
48
  it 'does not escape Angular interpolation marks in safe strings' do
45
- html.should include("{{safe}}")
46
- html.should_not include("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}safe}}")
49
+ expect(html).to include("{{safe}}")
50
+ expect(html).not_to include("{{ $root.DOUBLE_LEFT_CURLY_BRACE }}safe}}")
47
51
  end
48
52
 
49
53
  it 'does not escape Angular interpolation marks in a block where AngularXSS is disabled' do
@@ -52,8 +56,8 @@ shared_examples_for 'engine preventing Angular XSS' do |partial:|
52
56
  result = html
53
57
  end
54
58
 
55
- result.should include('{{unsafe}}')
56
- result.should_not include('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}')
59
+ expect(result).to include('{{unsafe}}')
60
+ expect(result).not_to include('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}')
57
61
  end
58
62
 
59
63
  it 'does escape Angular interpolation marks after the block where AngularXSS is disabled' do
@@ -61,27 +65,27 @@ shared_examples_for 'engine preventing Angular XSS' do |partial:|
61
65
  end
62
66
  result = html
63
67
 
64
- result.should include('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}')
65
- result.should_not include('{{unsafe}}')
68
+ expect(result).to include('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}')
69
+ expect(result).not_to include('{{unsafe}}')
66
70
  end
67
71
 
68
72
  it 'is not confused by exceptions in disable blocks' do
69
73
  class SomeException < StandardError; end
70
74
 
71
- proc {
75
+ expect do
72
76
  AngularXss.disable do
73
77
  raise SomeException
74
78
  end
75
- }.should raise_error(SomeException)
79
+ end.to raise_error(SomeException)
76
80
 
77
- html.should include('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}')
78
- html.should_not include('{{unsafe}}')
81
+ expect(html).to include('{{ $root.DOUBLE_LEFT_CURLY_BRACE }}unsafe}}')
82
+ expect(html).not_to include('{{unsafe}}')
79
83
  end
80
84
 
81
85
  it 'does not escape twice' do
82
86
  escaped = AngularXss::Escaper.escape('{{')
83
87
  double_escaped = AngularXss::Escaper.escape(escaped)
84
- html.should_not include(double_escaped)
88
+ expect(html).not_to include(double_escaped)
85
89
  end
86
90
 
87
91
  end