From 92fd2fc7dd105e901850fff8fb26b9b591fd0aa1 Mon Sep 17 00:00:00 2001 From: Jacob Burroughs Date: Mon, 20 Aug 2018 18:38:26 -0500 Subject: [PATCH 1/2] feat: Add support for configuration of XSLT security --- ext/java/nokogiri/XsltStylesheet.java | 9 ++++++++ ext/nokogiri/nokogiri.h | 1 + ext/nokogiri/xslt_stylesheet.c | 24 +++++++++++++++++++ lib/nokogiri/xslt.rb | 11 +++++++++ lib/nokogiri/xslt/security.rb | 33 +++++++++++++++++++++++++++ nokogiri.gemspec | 1 + test/files/xslt_included.xsl | 6 +++++ test/files/xslt_including.xsl | 7 ++++++ test/helper.rb | 1 + test/test_xslt_transforms.rb | 22 ++++++++++++++++++ 10 files changed, 115 insertions(+) create mode 100644 lib/nokogiri/xslt/security.rb create mode 100644 test/files/xslt_included.xsl create mode 100644 test/files/xslt_including.xsl diff --git a/ext/java/nokogiri/XsltStylesheet.java b/ext/java/nokogiri/XsltStylesheet.java index b729696481d..64e42e825bd 100644 --- a/ext/java/nokogiri/XsltStylesheet.java +++ b/ext/java/nokogiri/XsltStylesheet.java @@ -356,4 +356,13 @@ public class XsltStylesheet extends RubyObject return context.getRuntime().getNil(); */ } + + @JRubyMethod(meta = true, rest = true) + public static IRubyObject + set_default_security_prefs(ThreadContext context, IRubyObject klazz, IRubyObject[] args) + { + // This method is not supported because the Java XML backend does not support the + // security controls supported by the libxml backend + throw context.getRuntime().newNotImplementedError("Nokogiri::XSLT.set_default_security_prefs method is not implemented"); + } } diff --git a/ext/nokogiri/nokogiri.h b/ext/nokogiri/nokogiri.h index 63549ecec54..cfbbedb5d4f 100644 --- a/ext/nokogiri/nokogiri.h +++ b/ext/nokogiri/nokogiri.h @@ -49,6 +49,7 @@ #include #include #include +#include #include #include diff --git a/ext/nokogiri/xslt_stylesheet.c b/ext/nokogiri/xslt_stylesheet.c index d81a98124a6..02641447675 100644 --- a/ext/nokogiri/xslt_stylesheet.c +++ b/ext/nokogiri/xslt_stylesheet.c @@ -345,6 +345,29 @@ registr(VALUE self, VALUE uri, VALUE obj) return self; } +int +add_sec_pref(VALUE key, VALUE val, VALUE in) +{ + xsltSecurityPrefsPtr xsltPrefs = (xsltSecurityPrefsPtr) in; + if (val == Qtrue) { + xsltSetSecurityPrefs(xsltPrefs, NUM2INT(key), xsltSecurityAllow); + } else if (val == Qfalse) { + xsltSetSecurityPrefs(xsltPrefs, NUM2INT(key), xsltSecurityForbid); + } + + return ST_CONTINUE; +} + +static VALUE +set_default_security_prefs(VALUE self, VALUE prefs) +{ + Check_Type(prefs, T_HASH); + xsltSecurityPrefsPtr xsltPrefs = xsltNewSecurityPrefs(); + rb_hash_foreach(prefs, add_sec_pref, (VALUE)xsltPrefs); + xsltSetDefaultSecurityPrefs(xsltPrefs); + return Qnil; +} + void noko_init_xslt_stylesheet() { @@ -356,6 +379,7 @@ noko_init_xslt_stylesheet() rb_undef_alloc_func(cNokogiriXsltStylesheet); rb_define_singleton_method(cNokogiriXsltStylesheet, "parse_stylesheet_doc", parse_stylesheet_doc, 1); + rb_define_singleton_method(cNokogiriXsltStylesheet, "set_default_security_prefs", set_default_security_prefs, 1); rb_define_method(cNokogiriXsltStylesheet, "serialize", serialize, 1); rb_define_method(cNokogiriXsltStylesheet, "transform", transform, -1); } diff --git a/lib/nokogiri/xslt.rb b/lib/nokogiri/xslt.rb index 77d8ffaa266..2a46edb8109 100644 --- a/lib/nokogiri/xslt.rb +++ b/lib/nokogiri/xslt.rb @@ -1,6 +1,8 @@ # coding: utf-8 # frozen_string_literal: true +require_relative "xslt/security" + module Nokogiri class << self ### @@ -19,6 +21,8 @@ def XSLT(stylesheet, modules = {}) # See Nokogiri::XSLT::Stylesheet for creating and manipulating # Stylesheet object. module XSLT + include Nokogiri::XSLT::Security + class << self ### # Parse the stylesheet in +string+, register any +modules+ @@ -35,6 +39,13 @@ def parse(string, modules = {}) end end + ### + # Set the default security options used by libxslt + # +prefs+ should be an object of type Nokogiri::XSLT::Security::Config + def set_default_security_prefs(prefs) + Stylesheet.set_default_security_prefs(Security.keys.map { |k, v| { v => prefs.send(k) } }.reduce(:merge)) + end + # :call-seq: # quote_params(params) → Array # diff --git a/lib/nokogiri/xslt/security.rb b/lib/nokogiri/xslt/security.rb new file mode 100644 index 00000000000..730b11647c7 --- /dev/null +++ b/lib/nokogiri/xslt/security.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module Nokogiri + module XSLT + module Security + class Config + attr_accessor :allow_read_file + attr_accessor :allow_write_file + attr_accessor :allow_create_directory + attr_accessor :allow_read_network + attr_accessor :allow_write_network + + def initialize + @allow_read_file = false + @allow_write_file = false + @allow_create_directory = false + @allow_read_network = false + @allow_write_network = false + end + end + + def self.keys + { + allow_read_file: 1, + allow_write_file: 2, + allow_create_directory: 3, + allow_read_network: 4, + allow_write_network: 5, + } + end + end + end +end diff --git a/nokogiri.gemspec b/nokogiri.gemspec index 77836a5560f..9cc62a1d302 100644 --- a/nokogiri.gemspec +++ b/nokogiri.gemspec @@ -310,6 +310,7 @@ Gem::Specification.new do |spec| "lib/nokogiri/xml/xpath/syntax_error.rb", "lib/nokogiri/xml/xpath_context.rb", "lib/nokogiri/xslt.rb", + "lib/nokogiri/xslt/security.rb", "lib/nokogiri/xslt/stylesheet.rb", "lib/xsd/xmlparser/nokogiri.rb", ] diff --git a/test/files/xslt_included.xsl b/test/files/xslt_included.xsl new file mode 100644 index 00000000000..8d32d8df513 --- /dev/null +++ b/test/files/xslt_included.xsl @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/test/files/xslt_including.xsl b/test/files/xslt_including.xsl new file mode 100644 index 00000000000..57d1849663d --- /dev/null +++ b/test/files/xslt_including.xsl @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/test/helper.rb b/test/helper.rb index 002bcd6a505..da06ffa128d 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -79,6 +79,7 @@ module TestBase XML_XINCLUDE_FILE = File.join(ASSETS_DIR, "xinclude.xml") XML_ATOM_FILE = File.join(ASSETS_DIR, "atom.xml") XSLT_FILE = File.join(ASSETS_DIR, "staff.xslt") + XSLT_INCLUDING_FILE = File.join(ASSETS_DIR, "xslt_including.xsl") XPATH_FILE = File.join(ASSETS_DIR, "slow-xpath.xml") def i_am_ruby_matching(gem_version_requirement_string) diff --git a/test/test_xslt_transforms.rb b/test/test_xslt_transforms.rb index 6c75b7d15c9..51383f6333d 100644 --- a/test/test_xslt_transforms.rb +++ b/test/test_xslt_transforms.rb @@ -187,6 +187,28 @@ def test_transform_with_quote_params assert_equal("Booyah", result_doc.at_css("h1").content) end + def test_set_default_security_prefs + sec_prefs = Nokogiri::XSLT::Security::Config.new + + if Nokogiri.jruby? + assert_raises(NotImplementedError) do + Nokogiri::XSLT.set_default_security_prefs(sec_prefs) + end + else + # Default should be secure + Nokogiri::XSLT.set_default_security_prefs(sec_prefs) + assert_raises(RuntimeError) { Nokogiri::XSLT(File.open(XSLT_INCLUDING_FILE)) } + + sec_prefs.allow_read_file = true + Nokogiri::XSLT.set_default_security_prefs(sec_prefs) + assert(doc = Nokogiri::XSLT(File.open(XSLT_INCLUDING_FILE))) + + sec_prefs.allow_read_file = false + Nokogiri::XSLT.set_default_security_prefs(sec_prefs) + assert_raises(RuntimeError) { Nokogiri::XSLT(File.open(XSLT_INCLUDING_FILE)) } + end + end + def test_exslt # see http://yokolet.blogspot.com/2010/10/pure-java-nokogiri-xslt-extension.html") skip_unless_libxml2("cannot get it working on JRuby") From fed92a8cab36295301f4b6ce7cb0d18d8d4d3915 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 10:26:54 +0000 Subject: [PATCH 2/2] build(deps-dev): update rubocop-minitest requirement from = 0.21.0 to 0.22.2 Updates the requirements on [rubocop-minitest](https://github.com/rubocop/rubocop-minitest) to permit the latest version. - [Release notes](https://github.com/rubocop/rubocop-minitest/releases) - [Changelog](https://github.com/rubocop/rubocop-minitest/blob/master/CHANGELOG.md) - [Commits](https://github.com/rubocop/rubocop-minitest/compare/v0.21.0...v0.22.2) --- updated-dependencies: - dependency-name: rubocop-minitest dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 5901229005a..f7b051431e5 100644 --- a/Gemfile +++ b/Gemfile @@ -29,7 +29,7 @@ group :development do # rubocop if Gem::Requirement.new("~> 3.0").satisfied_by?(Gem::Version.new(RUBY_VERSION)) gem "rubocop", "= 1.35.1" - gem "rubocop-minitest", "= 0.21.0" + gem "rubocop-minitest", "0.22.2" gem "rubocop-performance", "= 1.14.3" gem "rubocop-rake", "= 0.6.0" gem "rubocop-shopify", "= 2.9.0"