From f93c8a375ac9101cd5ed43cccf6f3b7b5c498014 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Jul 2026 15:49:29 +0100 Subject: [PATCH] Keep NONET when overriding Nokogiri parse options Passing RECOVER explicitly to Nokogiri::XML::Reader replaces the defaults (RECOVER | NONET | BIG_LINES) and silently drops NONET, allowing a crafted document to trigger outbound network requests via external DTD/entity references. Restore NONET at both streaming reader call sites. Co-Authored-By: Claude Fable 5 --- lib/ndr_import/file/xml.rb | 5 +++-- lib/ndr_import/helpers/file/xml_streaming.rb | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/ndr_import/file/xml.rb b/lib/ndr_import/file/xml.rb index 2c7c631..5dfd414 100644 --- a/lib/ndr_import/file/xml.rb +++ b/lib/ndr_import/file/xml.rb @@ -57,8 +57,9 @@ def stream_metadata_values def metadata_from_stream(xpath) cursor = Cursor.new(xpath, false) - # If markup isn't well-formed, try to work around it: - options = Nokogiri::XML::ParseOptions::RECOVER + # If markup isn't well-formed, try to work around it (but keep NONET, + # so external entities/DTDs can't trigger network requests): + options = Nokogiri::XML::ParseOptions::RECOVER | Nokogiri::XML::ParseOptions::NONET reader = Nokogiri::XML::Reader(@stream, nil, @encoding, options) reader.each do |node| diff --git a/lib/ndr_import/helpers/file/xml_streaming.rb b/lib/ndr_import/helpers/file/xml_streaming.rb index 4a7c929..709c7e9 100644 --- a/lib/ndr_import/helpers/file/xml_streaming.rb +++ b/lib/ndr_import/helpers/file/xml_streaming.rb @@ -183,8 +183,9 @@ def stream_xml_nodes(io, node_xpath, pattern_match_xpath, encoding = nil) # Track nesting as the cursor moves through the document: cursor = Cursor.new(node_xpath, pattern_match_xpath) - # If markup isn't well-formed, try to work around it: - options = Nokogiri::XML::ParseOptions::RECOVER + # If markup isn't well-formed, try to work around it (but keep NONET, + # so external entities/DTDs can't trigger network requests): + options = Nokogiri::XML::ParseOptions::RECOVER | Nokogiri::XML::ParseOptions::NONET reader = Nokogiri::XML::Reader(io, nil, encoding, options) reader.each do |node|