Upgrade nokogiri to 1.19.4#2943
Conversation
Security patch (v1.19.3 → v1.19.4): 9 advisories, all low/medium and backwards-compatible. Per-app upgrade analysis: clean, zero app-code mitigations required. Both Gemfile.lock and Gemfile.saas.lock bumped (SaaS lock synced via bin/bundle-drift forward). Tests green (1509 unit + 12 system, 0 failures); all audits pass. Only bin/ci red is the gh signoff ceremony, which refuses to run on an uncommitted branch.
There was a problem hiding this comment.
Copilot wasn't able to review any files in this pull request.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
🤖 Upgrade analysis: nokogiri v1.19.3..v1.19.4 for fizzyUpgrade Plan: nokogiri v1.19.3..v1.19.4 for fizzy
Summary
nokogiri v1.19.4 is a pure security release. It bundles 9 security advisories (8 CRuby, 1 JRuby), all low/medium severity and all backwards-compatible hardening. No public API was removed or renamed. Every commit above "no impact" was searched against fizzy's own Recommendation: upgrade. This is a low-risk, security-motivated patch bump that fizzy should take. Zero app-code mitigations required. fizzy runs on CRuby, so the lone JRuby advisory (GHSA-8678-w3jw-xfc2) does not apply to its deployments. How fizzy depends on nokogirinokogiri is not a direct entry in fizzy's Application call sites (all safe)
Test-only call sites (all safe)
Transitive
|
| Commit | Summary | Impact Level | Advisory |
|---|---|---|---|
| 873948ac | Node#initialize_copy_with_args rejects non-Node sources |
unlikely impact | GHSA-g9g8-vgvw-g3vf |
| 4ec1264a | Document#root= rejects non-element nodes |
likely impact | GHSA-wjv4-x9w8-wm3h |
| 5524fa97 | Document#root= rejects non-element nodes (v1.19.x backport merge) |
likely impact | GHSA-wjv4-x9w8-wm3h |
| 6326471e | CRuby UAF in XML::Attr#value= / #content= |
unlikely impact | GHSA-phwj-rprq-35pp |
| e63c52c7 | NPE on uninitialized XML::Node structs (raise instead of crash) |
unlikely impact | GHSA-9cv2-cfxc-v4v2 |
| 7799fbd3 | NPE on uninitialized XML::Node structs (v1.19.x backport merge) |
unlikely impact | GHSA-9cv2-cfxc-v4v2 |
| 5fa63fff | CRuby UAF in XPathContext document lifetime |
unlikely impact | GHSA-p67v-3w7g-wjg7 |
| 41cc958d | CRuby out-of-bounds read in NodeSet#[] with large negative index |
unlikely impact | GHSA-5prr-v3j2-97mh |
| 04a09ddd | OOB read in NodeSet#[] (v1.19.x backport merge) |
unlikely impact | GHSA-5prr-v3j2-97mh |
| 0cb4b05f | UAF in Node#do_xinclude (adds safe_copy: kwarg, default true) |
likely impact | GHSA-wfpw-mmfh-qq69 |
| 07aa3918 | UAF in Node#do_xinclude (v1.19.x backport merge) |
likely impact | GHSA-wfpw-mmfh-qq69 |
| 39d26fea | CRuby UAF in Document#encoding= when setter raises |
unlikely impact | GHSA-5v8h-3h3q-446p |
| 6a0aa1e7 | UAF in Document#encoding= (v1.19.x backport merge) |
unlikely impact | GHSA-5v8h-3h3q-446p |
| f658a54a | JRuby NONET bypass in XML::Schema (SSRF/XXE) |
likely impact | GHSA-8678-w3jw-xfc2 |
| 8cfb9daa | version bump to v1.19.4 (CHANGELOG + VERSION) | unlikely impact | (release marker) |
Notes on "likely impact" commits
Four commits were rated "likely impact" at recon because they change observable public-API behavior. None of them apply to fizzy (confirmed across fizzy source AND all gem dependency dirs):
Document#root=now raisesTypeErrorfor non-element nodes (DTD/text/comment). No code in fizzy or its dependencies assigns a non-element node as a document root (zero.root =,create_internal_subset, orcreate_external_subsetmatches outside nokogiri itself).Node#do_xincludenow defaults tosafe_copy: true(detaches processed<xi:include>nodes, returnsself, raises on unlinked include nodes).Document.parseopts back into the old in-place path viasafe_copy: false, so the common parse-time XInclude path is unchanged. fizzy does no XInclude processing (zerodo_xinclude/process_xincludes/XINCLUDEmatches outside nokogiri).- CRuby
NodeSet#[]OOB read is a defensive bounds-check for pathological large-magnitude negative indices (e.g.-4294967297); normal subscripting ([0],.first,[-1]) is unchanged. fizzy's onlyNodeSetuse constructs one and appends with<<— it never subscripts. - JRuby
XML::SchemaNONET enforcement now blocks https/jar/UNC/remote-file/relative-remote schema resolution (previously only http/ftp). fizzy does no XSD schema parsing (zeroNokogiri::XML::Schemamatches), and 37signals runs on CRuby/MRI where this change is purely additive.
Security Advisories Addressed (nokogiri v1.19.4)
All from the v1.19.4 CHANGELOG:
| Severity | Backend | Advisory | Description |
|---|---|---|---|
| Low | CRuby | GHSA-g9g8-vgvw-g3vf | Invalid memory read in Node#initialize_copy_with_args with non-Node arg |
| Low | CRuby | GHSA-p67v-3w7g-wjg7 | UAF when XPathContext used after source document GC'd |
| Low | CRuby | GHSA-wfpw-mmfh-qq69 | UAF during XInclude processing via Node#do_xinclude |
| Low | CRuby | GHSA-wjv4-x9w8-wm3h | UAF when Document#root= assigned a non-element node |
| Low | CRuby | GHSA-phwj-rprq-35pp | UAF setting attribute value via XML::Attr#value= / #content= |
| Low | CRuby | GHSA-9cv2-cfxc-v4v2 | Null pointer deref calling methods on uninitialized wrapper objects (via allocate); now raises instead of crashing |
| Low | CRuby | GHSA-5v8h-3h3q-446p | UAF when Document#encoding= raises an exception |
| Medium | CRuby | GHSA-5prr-v3j2-97mh | Out-of-bounds read in XML::NodeSet#[] (#slice) with a large negative index |
| Low | JRuby | GHSA-8678-w3jw-xfc2 | XML::Schema did not enforce NONET on JRuby (SSRF/XXE; CVE-2020-26247 mitigation bypass) |
fizzy runs on CRuby; the lone JRuby advisory (GHSA-8678-w3jw-xfc2) does not apply to CRuby deployments.
No Impact (Skipped at Recon)
11 commits assessed as "no impact" during recon and not analyzed against fizzy:
- 7 dev/test/style commits: 49564997, fedcf44c, 55f3e2ec, 96a1c69e (valgrind/memory-debugger test tooling), b3368dec (skip int-truncation tests where long==int), 3bb38795 (rubocop style), 8b98649d (merge of the valgrind-assertion branch).
- 4 content-free merge commits whose substantive changes are carried by their parents (which ARE in range and were analyzed): ed85adcc, 9891ad10, ef19e132, a856d1e4.
Caveats / Verification Notes
- No caveats.
bundle show --pathsexits 0 with all 164 gems installed, includingnokogiri-1.19.4-x86_64-linux-gnu. Every above-"no impact" commit's patterns were searched across fizzy'sapp//lib//config//test/and all gemlibdirectories. The only matches in gem dirs were inside nokogiri's own 1.19.4 library code (the fixed version), the safeDocument#encoding=String-arg sites in loofah/actiontext, and benignNodeSet.newconstructions in rails-dom-testing. - The platform-specific precompiled gem (
nokogiri-1.19.4-x86_64-linux-gnu) ships a compiled native extension; the C source diff for the range lives upstream and does not affect fizzy at runtime (fizzy consumes the precompiled binary, not the C source). - Lockfile diff vs
origin/mainis nokogiri-only across both lockfiles: all 8 platform variants1.19.3→1.19.4inGemfile.lockandGemfile.saas.lock, no other gem changed. Full working-tree diff is exactly those two files (16 insertions / 16 deletions). - CI result: full
bin/cigreen. Unit suite 1509 tests / 5760 assertions, 0 failures/0 errors/0 skips; SQLite system suite 12 tests / 41 assertions, 0 failures/0 errors/0 skips. All security audits pass (bundler-audit: no vulnerabilities; brakeman: 0 warnings; importmap audit; gitleaks: no leaks). No pre-existing red. (fizzy defaults to OSS mode —Fizzy.saas?is false with no master key — so CI runs the SQLite test path and needs no Rails credentials.) - Runtime sanity:
Nokogiri::VERSIONandNokogiri::VERSION_INFO["nokogiri"]["version"]both report1.19.4under the installed gem.
Summary
Upgrade nokogiri 1.19.3 → 1.19.4 — pure security release. 9 advisories (8 CRuby, 1 JRuby), all low/medium and backwards-compatible. Per-app analysis: clean — zero app-code mitigations required.
Verification
Gemfile.lockandGemfile.saas.lock; no1.19.3references remain. (Gemfile.saas.locksynced viabin/bundle-drift forwardso the OSS/SaaS drift check passes.)Nokogiri::HTML.fragment,Nokogiri::HTML5, andNokogiri::XML::NodeSet.new(+<<) in three app files; none touch a patched API. The only transitiveDocument#encoding=call sites (loofah, actiontext) pass valid String args, so the encoding-UAF fix path is never exercised. fizzy's loneNodeSetuse constructs and appends — it never subscripts, so theNodeSet#[]OOB fix is irrelevant. Searchedapp/,lib/,config/,test/and all 164 installed gem dirs.bin/cired is the finalgh signoffceremony, which by design refuses to run on an uncommitted/unpushed branch ("repository has uncommitted or unpushed changes") — unrelated to nokogiri.Advisories addressed
GHSA-5prr-v3j2-97mh (Medium), GHSA-g9g8-vgvw-g3vf, GHSA-p67v-3w7g-wjg7, GHSA-wfpw-mmfh-qq69, GHSA-wjv4-x9w8-wm3h, GHSA-phwj-rprq-35pp, GHSA-9cv2-cfxc-v4v2, GHSA-5v8h-3h3q-446p, GHSA-8678-w3jw-xfc2 (JRuby).