diff --git a/Gemfile b/Gemfile index 89b42534ce..bdad189046 100644 --- a/Gemfile +++ b/Gemfile @@ -52,7 +52,7 @@ gem 'will_paginate', '~> 3.1' gem 'yaml_db' gem 'rails_autolink' gem 'rfc-822' -gem 'nokogiri', '~> 1.16.2' +gem 'nokogiri', '~> 1.16.5' #necessary for newer hashie dependency, original api_smith is no longer active gem 'api_smith', git: 'https://github.com/youroute/api_smith.git', ref: '1fb428cebc17b9afab25ac9f809bde87b0ec315b' gem 'rdf-virtuoso', '>= 0.2.0' @@ -134,7 +134,7 @@ gem 'request_store' gem 'bundler', '>= 1.8.4' -gem 'ro-crate', '~> 0.5.1' +gem 'ro-crate', '~> 0.5.2' gem 'rugged' gem 'i18n-js' diff --git a/Gemfile.lock b/Gemfile.lock index d3e795ca4e..946308413a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -460,7 +460,7 @@ GEM nokogiri (~> 1) rake mini_mime (1.1.5) - mini_portile2 (2.8.5) + mini_portile2 (2.8.6) minitest (5.20.0) minitest-reporters (1.5.0) ansi @@ -492,7 +492,7 @@ GEM net-protocol netrc (0.11.0) nio4r (2.7.0) - nokogiri (1.16.2) + nokogiri (1.16.5) mini_portile2 (~> 2.8.2) racc (~> 1.4) nori (1.1.5) @@ -737,7 +737,7 @@ GEM json (~> 2.3.0) ucf (~> 2.0.2) uuid (~> 2.3) - ro-crate (0.5.1) + ro-crate (0.5.2) addressable (>= 2.7, < 2.9) rubyzip (~> 2.0.0) rsolr (2.5.0) @@ -1028,7 +1028,7 @@ DEPENDENCIES my_responds_to_parent! mysql2 net-ftp - nokogiri (~> 1.16.2) + nokogiri (~> 1.16.5) omniauth (~> 2.1.0) omniauth-github omniauth-rails_csrf_protection @@ -1069,7 +1069,7 @@ DEPENDENCIES rfc-822 rmagick (= 5.3.0) ro-bundle (~> 0.3.0) - ro-crate (~> 0.5.1) + ro-crate (~> 0.5.2) rspec-rails (~> 5.1) rubocop ruby-prof diff --git a/app/assets/javascripts/objects_input.js b/app/assets/javascripts/objects_input.js index 3bcb08fd06..ad421c1ae1 100644 --- a/app/assets/javascripts/objects_input.js +++ b/app/assets/javascripts/objects_input.js @@ -32,9 +32,8 @@ var ObjectsInput = { const template = $j(this).data('typeahead-template') || 'typeahead/hint'; opts.templateResult = HandlebarsTemplates[template]; - opts.escapeMarkup = function (m) { - return m; - } + opts.escapeMarkup = ObjectsInput.doNothing; + opts.templateSelection = ObjectsInput.escapeSelectionMarkup; if ($j(this).data('typeahead-query-url')) { opts.ajax={ @@ -47,6 +46,12 @@ var ObjectsInput = { opts ); }); + }, + doNothing: function (m) { + return m; + }, + escapeSelectionMarkup: function (m) { + return jQuery.fn.select2.defaults.defaults.escapeMarkup(m.text); } } $j(document).ready(function () { diff --git a/app/assets/javascripts/single_page/dynamic_table.js.erb b/app/assets/javascripts/single_page/dynamic_table.js.erb index 0827ff286a..ae1a9cc598 100644 --- a/app/assets/javascripts/single_page/dynamic_table.js.erb +++ b/app/assets/javascripts/single_page/dynamic_table.js.erb @@ -19,6 +19,33 @@ const defaultCols = [{ } }]; +// Sanitizes input data to prevent XSS attacks +// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html +function sanitizeHTML(str) { + return str.replace(/[&<>"']/g, function(match) { + return { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }[match]; + }); +} + +function sanitizeData(data) { + if (typeof data === 'string' && data !== "") { + return sanitizeHTML(data); + } else if(typeof data === 'array'){ + return data.forEach((e) => { + sanitizeData(e); + }); + } else { + // Handle other data types or nested objects/arrays if necessary + return data; + } +} + const objectInputTemp = '' + '