From 3263a137a1aee366ca86f1fe5fe066c8a48160d2 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 29 Mar 2023 23:53:26 +0000 Subject: Add latest changes from gitlab-org/security/gitlab@15-8-stable-ee --- .../behaviors/markdown/render_observability.js | 45 ++++++++++++------- lib/banzai/filter/inline_observability_filter.rb | 15 +++++-- .../markdown/render_observability_spec.js | 12 ++++- .../filter/inline_observability_filter_spec.rb | 52 ++++++++++++++++++++++ 4 files changed, 103 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/behaviors/markdown/render_observability.js b/app/assets/javascripts/behaviors/markdown/render_observability.js index 704d85cf22e..d5d46c10efd 100644 --- a/app/assets/javascripts/behaviors/markdown/render_observability.js +++ b/app/assets/javascripts/behaviors/markdown/render_observability.js @@ -7,23 +7,36 @@ export function getFrameSrc(url) { } const mountVueComponent = (element) => { - const url = [element.dataset.frameUrl]; + const { frameUrl, observabilityUrl } = element.dataset; - return new Vue({ - el: element, - render(h) { - return h('iframe', { - style: { - height: '366px', - width: '768px', - }, - attrs: { - src: getFrameSrc(url), - frameBorder: '0', - }, - }); - }, - }); + try { + if ( + !observabilityUrl || + !frameUrl || + new URL(frameUrl)?.host !== new URL(observabilityUrl).host + ) + return; + + // eslint-disable-next-line no-new + new Vue({ + el: element, + render(h) { + return h('iframe', { + style: { + height: '366px', + width: '768px', + }, + attrs: { + src: getFrameSrc(frameUrl), + frameBorder: '0', + }, + }); + }, + }); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + } }; export default function renderObservability(elements) { diff --git a/lib/banzai/filter/inline_observability_filter.rb b/lib/banzai/filter/inline_observability_filter.rb index 334c04f2b59..883965ccae0 100644 --- a/lib/banzai/filter/inline_observability_filter.rb +++ b/lib/banzai/filter/inline_observability_filter.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +require 'uri' module Banzai module Filter @@ -15,7 +16,8 @@ module Banzai doc.document.create_element( 'div', class: 'js-render-observability', - 'data-frame-url': url + 'data-frame-url': url, + 'data-observability-url': Gitlab::Observability.observability_url ) end @@ -28,8 +30,15 @@ module Banzai # obtained from the target link def element_to_embed(node) url = node['href'] - - create_element(url) + uri = URI.parse(url) + observability_uri = URI.parse(Gitlab::Observability.observability_url) + + if uri.scheme == observability_uri.scheme && + uri.port == observability_uri.port && + uri.host.casecmp?(observability_uri.host) && + uri.path.downcase.exclude?("auth/start") + create_element(url) + end end private diff --git a/spec/frontend/behaviors/markdown/render_observability_spec.js b/spec/frontend/behaviors/markdown/render_observability_spec.js index c87d11742dc..03a0cb2fcc2 100644 --- a/spec/frontend/behaviors/markdown/render_observability_spec.js +++ b/spec/frontend/behaviors/markdown/render_observability_spec.js @@ -16,7 +16,7 @@ describe('Observability iframe renderer', () => { }); it('renders an observability iframe', () => { - document.body.innerHTML = `
`; + document.body.innerHTML = `
`; expect(findObservabilityIframes()).toHaveLength(0); @@ -26,7 +26,7 @@ describe('Observability iframe renderer', () => { }); it('renders iframe with dark param when GL has dark theme', () => { - document.body.innerHTML = `
`; + document.body.innerHTML = `
`; jest.spyOn(ColorUtils, 'darkModeEnabled').mockImplementation(() => true); expect(findObservabilityIframes('dark')).toHaveLength(0); @@ -35,4 +35,12 @@ describe('Observability iframe renderer', () => { expect(findObservabilityIframes('dark')).toHaveLength(1); }); + + it('does not render if url is different from observability url', () => { + document.body.innerHTML = `
`; + + renderEmbeddedObservability(); + + expect(findObservabilityIframes()).toHaveLength(0); + }); }); diff --git a/spec/lib/banzai/filter/inline_observability_filter_spec.rb b/spec/lib/banzai/filter/inline_observability_filter_spec.rb index fb1ba46e76c..69a9dc96c2c 100644 --- a/spec/lib/banzai/filter/inline_observability_filter_spec.rb +++ b/spec/lib/banzai/filter/inline_observability_filter_spec.rb @@ -34,6 +34,58 @@ RSpec.describe Banzai::Filter::InlineObservabilityFilter do end end + context 'when the document contains an embeddable observability link with redirect' do + let(:url) { 'https://observe.gitlab.com@example.com/12345' } + + it 'leaves the original link unchanged' do + expect(doc.at_css('a').to_s).to eq(input) + end + + it 'does not append an observability charts placeholder' do + node = doc.at_css('.js-render-observability') + + expect(node).not_to be_present + end + end + + context 'when the document contains an embeddable observability link with different port' do + let(:url) { 'https://observe.gitlab.com:3000/12345' } + let(:observe_url) { 'https://observe.gitlab.com:3001' } + + before do + stub_env('OVERRIDE_OBSERVABILITY_URL', observe_url) + end + + it 'leaves the original link unchanged' do + expect(doc.at_css('a').to_s).to eq(input) + end + + it 'does not append an observability charts placeholder' do + node = doc.at_css('.js-render-observability') + + expect(node).not_to be_present + end + end + + context 'when the document contains an embeddable observability link with auth/start' do + let(:url) { 'https://observe.gitlab.com/auth/start' } + let(:observe_url) { 'https://observe.gitlab.com' } + + before do + stub_env('OVERRIDE_OBSERVABILITY_URL', observe_url) + end + + it 'leaves the original link unchanged' do + expect(doc.at_css('a').to_s).to eq(input) + end + + it 'does not append an observability charts placeholder' do + node = doc.at_css('.js-render-observability') + + expect(node).not_to be_present + end + end + context 'when feature flag is disabled' do let(:url) { 'https://observe.gitlab.com/12345' } -- cgit v1.2.1