diff --git a/CHANGELOG b/CHANGELOG index 0224a0ed7..2f669dcd0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -[v#.#.#] ([month] [YYYY]) +v4.15.0 (December 2024) - Tags: Add custom ordering - Welcome Kit: - Add HTML report template @@ -6,28 +6,10 @@ - Update OWASP Top 10 methodology to latest version (2021) - Upgraded gems: - rails, rexml - - Bugs fixes: - - [entity]: - - [future tense verb] [bug fix] - - Bug tracker items: - - [item] - - New integrations: - - [integration] - - Integration enhancements: - - [integration]: - - [future tense verb] [integration enhancement] - - [integration bug fixes]: - - [future tense verb] [integration bug fix] - - Reporting enhancements: - - [report type]: - - [future tense verb] [reporting enhancement] - - REST/JSON API enhancements: - - [API entity]: - - [future tense verb] [API enhancement] + - Integration enhancements: + - Qualys: Add `cvss3_base`, `cvss3_temporal`, and `cvss3_version` as available vuln fields - Security Fixes: - - High: (Authenticated|Unauthenticated) (admin|author|contributor) [vulnerability description] - - Medium: (Authenticated|Unauthenticated) (admin|author|contributor) [vulnerability description] - - Low: (Authenticated|Unauthenticated) (admin|author|contributor) [vulnerability description] + - High: Authenticated (author) persistent cross-site scripting v4.14.0 (October 2024) - Kit Import: Use file name sequencing when a template file with the same name exists diff --git a/Gemfile b/Gemfile index ac479684f..d7332b46c 100644 --- a/Gemfile +++ b/Gemfile @@ -216,12 +216,12 @@ end # # Base framework classes required by other plugins -gem 'dradis-plugins', '~> 4.14.0' +gem 'dradis-plugins', '~> 4.15.0' gem 'dradis-api', path: 'engines/dradis-api' # Import / export project data -gem 'dradis-projects', '~> 4.14.0' +gem 'dradis-projects', '~> 4.15.0' plugins_file = 'Gemfile.plugins' if File.exists?(plugins_file) @@ -233,33 +233,33 @@ end # ----------------------------------------------------------------- Calculators -gem 'dradis-calculator_cvss', '~> 4.14.0' -gem 'dradis-calculator_dread', '~> 4.14.0' +gem 'dradis-calculator_cvss', '~> 4.15.0' +gem 'dradis-calculator_dread', '~> 4.15.0' # ---------------------------------------------------------------------- Export -gem 'dradis-csv_export', '~> 4.14.0' -gem 'dradis-html_export', '~> 4.14.0' +gem 'dradis-csv_export', '~> 4.15.0' +gem 'dradis-html_export', '~> 4.15.0' # ---------------------------------------------------------------------- Import -gem 'dradis-csv', '~> 4.14.0' +gem 'dradis-csv', '~> 4.15.0' # ---------------------------------------------------------------------- Upload -gem 'dradis-acunetix', '~> 4.14.0' -gem 'dradis-brakeman', '~> 4.14.0' -gem 'dradis-burp', '~> 4.14.0' -gem 'dradis-coreimpact', '~> 4.14.0' -gem 'dradis-metasploit', '~> 4.14.0' -gem 'dradis-nessus', '~> 4.14.0' -gem 'dradis-netsparker', '~> 4.14.0' -gem 'dradis-nexpose', '~> 4.14.0' -gem 'dradis-nikto', '~> 4.14.0' -gem 'dradis-nipper', '~> 4.14.0' -gem 'dradis-nmap', '~> 4.14.0' -gem 'dradis-ntospider', '~> 4.14.0' -gem 'dradis-openvas', '~> 4.14.0' -gem 'dradis-pentera', '~> 4.14.0' -gem 'dradis-qualys', '~> 4.14.0' -gem 'dradis-saint', '~> 4.14.0' -gem 'dradis-veracode', '~> 4.14.0' -gem 'dradis-wpscan', '~> 4.14.0' -gem 'dradis-zap', '~> 4.14.0' +gem 'dradis-acunetix', '~> 4.15.0' +gem 'dradis-brakeman', '~> 4.15.0' +gem 'dradis-burp', '~> 4.15.0' +gem 'dradis-coreimpact', '~> 4.15.0' +gem 'dradis-metasploit', '~> 4.15.0' +gem 'dradis-nessus', '~> 4.15.0' +gem 'dradis-netsparker', '~> 4.15.0' +gem 'dradis-nexpose', '~> 4.15.0' +gem 'dradis-nikto', '~> 4.15.0' +gem 'dradis-nipper', '~> 4.15.0' +gem 'dradis-nmap', '~> 4.15.0' +gem 'dradis-ntospider', '~> 4.15.0' +gem 'dradis-openvas', '~> 4.15.0' +gem 'dradis-pentera', '~> 4.15.0' +gem 'dradis-qualys', '~> 4.15.0' +gem 'dradis-saint', '~> 4.15.0' +gem 'dradis-veracode', '~> 4.15.0' +gem 'dradis-wpscan', '~> 4.15.0' +gem 'dradis-zap', '~> 4.15.0' diff --git a/Gemfile.lock b/Gemfile.lock index 666560776..8095ebcf1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: engines/dradis-api specs: - dradis-api (4.14.0) + dradis-api (4.15.0) jbuilder GEM @@ -127,73 +127,73 @@ GEM date (3.3.4) diff-lcs (1.5.0) differ (0.1.2) - dradis-acunetix (4.14.0) + dradis-acunetix (4.15.0) dradis-plugins (~> 4.0) nokogiri (~> 1.3) - dradis-brakeman (4.14.0) + dradis-brakeman (4.15.0) dradis-plugins (~> 4.0) - dradis-burp (4.14.0) + dradis-burp (4.15.0) dradis-plugins (~> 4.0) nokogiri (~> 1.3) - dradis-calculator_cvss (4.14.0) + dradis-calculator_cvss (4.15.0) dradis-plugins (~> 4.0) - dradis-calculator_dread (4.14.0) + dradis-calculator_dread (4.15.0) dradis-plugins (~> 4.0) - dradis-coreimpact (4.14.0) + dradis-coreimpact (4.15.0) dradis-plugins (~> 4.0) - dradis-csv (4.14.0) + dradis-csv (4.15.0) dradis-plugins (~> 4.0) - dradis-csv_export (4.14.0) + dradis-csv_export (4.15.0) dradis-plugins (>= 4.8.0) - dradis-html_export (4.14.0) + dradis-html_export (4.15.0) RedCloth (~> 4.3.2) dradis-plugins (>= 4.8.0) rails_autolink (~> 1.1) - dradis-metasploit (4.14.0) + dradis-metasploit (4.15.0) dradis-plugins (~> 4.0) nokogiri (~> 1.3) - dradis-nessus (4.14.0) + dradis-nessus (4.15.0) dradis-plugins (~> 4.0) nokogiri - dradis-netsparker (4.14.0) + dradis-netsparker (4.15.0) dradis-plugins (~> 4.0) nokogiri (>= 1.12.5) - dradis-nexpose (4.14.0) + dradis-nexpose (4.15.0) dradis-plugins (~> 4.0) nokogiri (~> 1.3) - dradis-nikto (4.14.0) + dradis-nikto (4.15.0) dradis-plugins (~> 4.0) nokogiri (~> 1.3) - dradis-nipper (4.14.0) + dradis-nipper (4.15.0) dradis-plugins (~> 4.0) - dradis-nmap (4.14.0) + dradis-nmap (4.15.0) dradis-plugins (~> 4.0) ruby-nmap (~> 0.7) - dradis-ntospider (4.14.0) + dradis-ntospider (4.15.0) dradis-plugins (~> 4.0) - dradis-openvas (4.14.0) + dradis-openvas (4.15.0) dradis-plugins (~> 4.0) - dradis-pentera (4.14.0) + dradis-pentera (4.15.0) dradis-plugins (~> 4.0) - dradis-plugins (4.14.0) - dradis-projects (4.14.0) + dradis-plugins (4.15.0) + dradis-projects (4.15.0) dradis-plugins (>= 4.8.0) rubyzip - dradis-qualys (4.14.0) + dradis-qualys (4.15.1) dradis-plugins (~> 4.0) nokogiri (~> 1.3) - dradis-saint (4.14.0) + dradis-saint (4.15.0) combustion (~> 0.6.0) dradis-plugins (~> 4.0) nokogiri rake (~> 13.0) rspec-rails - dradis-veracode (4.14.0) + dradis-veracode (4.15.0) dradis-plugins (~> 4.0) - dradis-wpscan (4.14.0) + dradis-wpscan (4.15.0) dradis-plugins (~> 4.0) multi_json - dradis-zap (4.14.0) + dradis-zap (4.15.0) dradis-plugins (~> 4.0) nokogiri (~> 1.3) erubi (1.13.0) @@ -530,33 +530,33 @@ DEPENDENCIES coffee-rails (~> 5.0) database_cleaner differ (~> 0.1.2) - dradis-acunetix (~> 4.14.0) + dradis-acunetix (~> 4.15.0) dradis-api! - dradis-brakeman (~> 4.14.0) - dradis-burp (~> 4.14.0) - dradis-calculator_cvss (~> 4.14.0) - dradis-calculator_dread (~> 4.14.0) - dradis-coreimpact (~> 4.14.0) - dradis-csv (~> 4.14.0) - dradis-csv_export (~> 4.14.0) - dradis-html_export (~> 4.14.0) - dradis-metasploit (~> 4.14.0) - dradis-nessus (~> 4.14.0) - dradis-netsparker (~> 4.14.0) - dradis-nexpose (~> 4.14.0) - dradis-nikto (~> 4.14.0) - dradis-nipper (~> 4.14.0) - dradis-nmap (~> 4.14.0) - dradis-ntospider (~> 4.14.0) - dradis-openvas (~> 4.14.0) - dradis-pentera (~> 4.14.0) - dradis-plugins (~> 4.14.0) - dradis-projects (~> 4.14.0) - dradis-qualys (~> 4.14.0) - dradis-saint (~> 4.14.0) - dradis-veracode (~> 4.14.0) - dradis-wpscan (~> 4.14.0) - dradis-zap (~> 4.14.0) + dradis-brakeman (~> 4.15.0) + dradis-burp (~> 4.15.0) + dradis-calculator_cvss (~> 4.15.0) + dradis-calculator_dread (~> 4.15.0) + dradis-coreimpact (~> 4.15.0) + dradis-csv (~> 4.15.0) + dradis-csv_export (~> 4.15.0) + dradis-html_export (~> 4.15.0) + dradis-metasploit (~> 4.15.0) + dradis-nessus (~> 4.15.0) + dradis-netsparker (~> 4.15.0) + dradis-nexpose (~> 4.15.0) + dradis-nikto (~> 4.15.0) + dradis-nipper (~> 4.15.0) + dradis-nmap (~> 4.15.0) + dradis-ntospider (~> 4.15.0) + dradis-openvas (~> 4.15.0) + dradis-pentera (~> 4.15.0) + dradis-plugins (~> 4.15.0) + dradis-projects (~> 4.15.0) + dradis-qualys (~> 4.15.0) + dradis-saint (~> 4.15.0) + dradis-veracode (~> 4.15.0) + dradis-wpscan (~> 4.15.0) + dradis-zap (~> 4.15.0) factory_bot_rails font-awesome-sass (~> 6.4.0) foreman diff --git a/app/assets/javascripts/shared/differ.js b/app/assets/javascripts/shared/differ.js new file mode 100644 index 000000000..8bd02dd9d --- /dev/null +++ b/app/assets/javascripts/shared/differ.js @@ -0,0 +1,37 @@ +class Differ { + constructor() { + this.delRegex = /\[31m([\s\S]*?)\[0m/g; + this.insRegex = /\[32m([\s\S]*?)\[0m/g; + } + + ansiToHTML(text) { + return text + .replace(this.delRegex, '$1') + .replace(this.insRegex, '$1'); + } + + highlightString(text, diffType) { + if (diffType === 'del') { + return text + .replace(this.delRegex, '$1') + .replace(this.insRegex, ''); + } + else if (diffType === 'ins') { + return text + .replace(this.insRegex, '$1') + .replace(this.delRegex, ''); + } + else { + console.log('Invalid diffType!'); + } + } +} + +document.addEventListener('turbolinks:load', function() { + if ($('.js-diff-body').length) { + let differ = new Differ(), + content = $('.js-diff-body').html(); + + $('.js-diff-body').html(differ.ansiToHTML(content)); + } +}); diff --git a/app/assets/javascripts/shared/revisions.js.coffee b/app/assets/javascripts/shared/revisions.js.coffee deleted file mode 100644 index 692424d1b..000000000 --- a/app/assets/javascripts/shared/revisions.js.coffee +++ /dev/null @@ -1,14 +0,0 @@ -document.addEventListener "turbolinks:load", -> - - if $('.js-diff-body').length - delRegex = /\[31m([\s\S]*?)\[0m/g - insRegex = /\[32m([\s\S]*?)\[0m/g - - diffText = $('.js-diff-body').html() - - newText = - diffText. - replace(delRegex, '$1'). - replace(insRegex, '$1') - - $('.js-diff-body').html(newText) diff --git a/app/assets/javascripts/tylium.js b/app/assets/javascripts/tylium.js index 8675ededf..8a78b8b2e 100644 --- a/app/assets/javascripts/tylium.js +++ b/app/assets/javascripts/tylium.js @@ -21,11 +21,11 @@ //= require shared/charts //= require shared/comments //= require shared/console_updater +//= require shared/differ //= require shared/editor_toolbar //= require shared/quote_selector //= require shared/mentions //= require shared/notifications -//= require shared/revisions //= require shared/rtp_validation //= require shared/state_button //= require shared/subscriptions diff --git a/app/models/comment.rb b/app/models/comment.rb index d0ddb8478..61e6fd0b6 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -47,7 +47,7 @@ def notify(action:, actor:, recipients:) # to be an ActiveRecord::Relation. subscribers = User.includes(:subscriptions).where( subscriptions: { subscribable_id: commentable.id, subscribable_type: commentable.class.to_s } - ).where.not(id: [user.id] + mentions.pluck(:id)) + ).where.not(id: [user.id] + mentions.pluck(:id)).enabled subscribers = subscribers.select { |user| Ability.new(user).can?(:read, self) } create_notifications(action: :create, actor: actor, recipients: subscribers) end @@ -87,7 +87,7 @@ def to_xml(xml_builder, version: 3) xml_builder.content do xml_builder.cdata!(content) end - xml_builder.author(user.email) + xml_builder.author(user&.email) xml_builder.created_at(created_at.to_i) end diff --git a/app/services/diffed_content.rb b/app/services/diffed_content.rb index 092a10c2e..8484ec327 100644 --- a/app/services/diffed_content.rb +++ b/app/services/diffed_content.rb @@ -84,12 +84,8 @@ def content_with_updated_field_from_target(field:, source:, target:) end def diff_by_word(source_content, target_content) - Differ.format = :html - differ_result = Differ.diff_by_word(source_content, target_content) - - output = highlighted_string(differ_result) - - { source: output[1], target: output[0] } + Differ.format = :color + Differ.diff_by_word(source_content, target_content) end def normalize_content(record) @@ -100,21 +96,4 @@ def normalize_content(record) "#[#{field}]#\n#{value.gsub("\r", '')}\n" end.join("\n") end - - def highlighted_string(differ_result) - [:delete, :insert].map do |highlight_type| - result_str = differ_result.dup.to_s - - case highlight_type - when :delete - result_str.gsub!(/(.*?)<\/del>/m, '\1') - result_str.gsub!(/(.*?)<\/ins>/m, '') - when :insert - result_str.gsub!(/(.*?)<\/ins>/m, '\1') - result_str.gsub!(/(.*?)<\/del>/m, '') - end - - result_str.html_safe - end - end end diff --git a/app/views/issues/update.json.erb b/app/views/issues/update.json.erb index aed67e7d0..417db53f4 100644 --- a/app/views/issues/update.json.erb +++ b/app/views/issues/update.json.erb @@ -2,6 +2,6 @@ "success": <%= @modified %>, <% if tag = @issue.tags.first %> "issue_link": "<%= j render(partial: 'issues/issue', locals: { issue: @issue }, formats: :html) %>", - "tag_cell": "<%= j " #{tag.display_name}".html_safe %>" + "tag_cell": "<%= j " #{tag.display_name}".html_safe %>" <% end %> } diff --git a/lib/dradis/ce/version.rb b/lib/dradis/ce/version.rb index 55c6e4b30..6432bc10d 100644 --- a/lib/dradis/ce/version.rb +++ b/lib/dradis/ce/version.rb @@ -2,7 +2,7 @@ module Dradis module CE #:nodoc: module VERSION #:nodoc: MAJOR = 4 - MINOR = 14 + MINOR = 15 TINY = 0 PRE = nil diff --git a/spec/services/diffed_content_spec.rb b/spec/services/diffed_content_spec.rb index d2024377c..7231c16be 100644 --- a/spec/services/diffed_content_spec.rb +++ b/spec/services/diffed_content_spec.rb @@ -8,10 +8,9 @@ describe '#content_diff' do it 'returns the diff' do - expect(subject.content_diff).to eq({ - source: "#[Title]#\nIssue1\n", - target: "#[Title]#\nIssue2\n" - }) + expect(subject.content_diff.to_s).to eq( + "#[Title]#\n\e[31mIssue2\e[0m\e[32mIssue1\e[0m\n" + ) end end @@ -33,12 +32,9 @@ describe '#unsynced_fields' do it 'returns the fields that have changed between the source and the target' do - expect(subject.unsynced_fields).to eq({ - 'Title' => { - source: 'Issue1', - target: 'Issue2' - } - }) + expect(subject.unsynced_fields['Title'].to_s).to eq( + "\e[31mIssue2\e[0m\e[32mIssue1\e[0m" + ) end end