Commit 52ade20e authored by Ruben Davila's avatar Ruben Davila

Merge 'dev/8-17-stable' into 8-17-stable

parents 872a530b 79b56c8a
8.17.0-rc1 8.17.0-rc2
...@@ -36,7 +36,7 @@ class FileUploader < GitlabUploader ...@@ -36,7 +36,7 @@ class FileUploader < GitlabUploader
escaped_filename = filename.gsub("]", "\\]") escaped_filename = filename.gsub("]", "\\]")
markdown = "[#{escaped_filename}](#{self.secure_url})" markdown = "[#{escaped_filename}](#{self.secure_url})"
markdown.prepend("!") if image_or_video? markdown.prepend("!") if image_or_video? || dangerous?
{ {
alt: filename, alt: filename,
......
# Extra methods for uploader # Extra methods for uploader
module UploaderHelper module UploaderHelper
IMAGE_EXT = %w[png jpg jpeg gif bmp tiff svg] IMAGE_EXT = %w[png jpg jpeg gif bmp tiff]
# We recommend using the .mp4 format over .mov. Videos in .mov format can # We recommend using the .mp4 format over .mov. Videos in .mov format can
# still be used but you really need to make sure they are served with the # still be used but you really need to make sure they are served with the
# proper MIME type video/mp4 and not video/quicktime or your videos won't play # proper MIME type video/mp4 and not video/quicktime or your videos won't play
# on IE >= 9. # on IE >= 9.
# http://archive.sublimevideo.info/20150912/docs.sublimevideo.net/troubleshooting.html # http://archive.sublimevideo.info/20150912/docs.sublimevideo.net/troubleshooting.html
VIDEO_EXT = %w[mp4 m4v mov webm ogv] VIDEO_EXT = %w[mp4 m4v mov webm ogv]
# These extension types can contain dangerous code and should only be embedded inline with
# proper filtering. They should always be tagged as "Content-Disposition: attachment", not "inline".
DANGEROUS_EXT = %w[svg]
def image? def image?
extension_match?(IMAGE_EXT) extension_match?(IMAGE_EXT)
...@@ -20,6 +23,10 @@ module UploaderHelper ...@@ -20,6 +23,10 @@ module UploaderHelper
image? || video? image? || video?
end end
def dangerous?
extension_match?(DANGEROUS_EXT)
end
def extension_match?(extensions) def extension_match?(extensions)
return false unless file return false unless file
......
---
title: Patch Asciidocs rendering to block XSS
merge_request:
author:
---
title: Fix XSS vulnerability in SVG attachments
merge_request:
author:
---
title: Prevent the GitHub importer from assigning labels and comments to merge requests or issues belonging to other projects.
merge_request:
author:
---
title: Patch XSS vulnerability in RDOC support
merge_request:
author:
class AddDevelopersCanMergeToProtectedBranches < ActiveRecord::Migration class AddDevelopersCanMergeToProtectedBranches < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction! disable_ddl_transaction!
def change def change
......
...@@ -36,6 +36,9 @@ module Gitlab ...@@ -36,6 +36,9 @@ module Gitlab
html = Banzai.post_process(html, context) html = Banzai.post_process(html, context)
filter = Banzai::Filter::SanitizationFilter.new(html)
html = filter.call.to_s
html.html_safe html.html_safe
end end
......
...@@ -115,7 +115,7 @@ module Gitlab ...@@ -115,7 +115,7 @@ module Gitlab
begin begin
issuable = issuable =
if gh_issue.pull_request? if gh_issue.pull_request?
MergeRequest.find_by_iid(gh_issue.number) MergeRequest.find_by(target_project_id: project.id, iid: gh_issue.number)
else else
gh_issue.create! gh_issue.create!
end end
...@@ -212,8 +212,12 @@ module Gitlab ...@@ -212,8 +212,12 @@ module Gitlab
comment = CommentFormatter.new(project, raw) comment = CommentFormatter.new(project, raw)
# GH does not return info about comment's parent, so we guess it by checking its URL! # GH does not return info about comment's parent, so we guess it by checking its URL!
*_, parent, iid = URI(raw.html_url).path.split('/') *_, parent, iid = URI(raw.html_url).path.split('/')
issuable_class = parent == 'issues' ? Issue : MergeRequest if parent == 'issues'
issuable = issuable_class.find_by_iid(iid) issuable = Issue.find_by(project_id: project.id, iid: iid)
else
issuable = MergeRequest.find_by(target_project_id: project.id, iid: iid)
end
next unless issuable next unless issuable
issuable.notes.create!(comment.attributes) issuable.notes.create!(comment.attributes)
......
...@@ -17,6 +17,9 @@ module Gitlab ...@@ -17,6 +17,9 @@ module Gitlab
html = Banzai.post_process(html, context) html = Banzai.post_process(html, context)
filter = Banzai::Filter::SanitizationFilter.new(html)
html = filter.call.to_s
html.html_safe html.html_safe
end end
end end
......
...@@ -4,6 +4,28 @@ describe UploadsController do ...@@ -4,6 +4,28 @@ describe UploadsController do
let!(:user) { create(:user, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } let!(:user) { create(:user, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) }
describe "GET show" do describe "GET show" do
context 'Content-Disposition security measures' do
let(:project) { create(:empty_project, :public) }
context 'for PNG files' do
it 'returns Content-Disposition: inline' do
note = create(:note, :with_attachment, project: project)
get :show, model: 'note', mounted_as: 'attachment', id: note.id, filename: 'image.png'
expect(response['Content-Disposition']).to start_with('inline;')
end
end
context 'for SVG files' do
it 'returns Content-Disposition: attachment' do
note = create(:note, :with_svg_attachment, project: project)
get :show, model: 'note', mounted_as: 'attachment', id: note.id, filename: 'image.svg'
expect(response['Content-Disposition']).to start_with('attachment;')
end
end
end
context "when viewing a user avatar" do context "when viewing a user avatar" do
context "when signed in" do context "when signed in" do
before do before do
......
...@@ -97,7 +97,11 @@ FactoryGirl.define do ...@@ -97,7 +97,11 @@ FactoryGirl.define do
end end
trait :with_attachment do trait :with_attachment do
attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "`/png") } attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png") }
end
trait :with_svg_attachment do
attachment { fixture_file_upload(Rails.root + "spec/fixtures/unsanitized.svg", "image/svg+xml") }
end end
end end
end end
...@@ -41,6 +41,29 @@ module Gitlab ...@@ -41,6 +41,29 @@ module Gitlab
render(input, context, asciidoc_opts) render(input, context, asciidoc_opts)
end end
end end
context "XSS" do
links = {
'links' => {
input: 'link:mylink"onmouseover="alert(1)[Click Here]',
output: "<div>\n<p><a href=\"mylink\">Click Here</a></p>\n</div>"
},
'images' => {
input: 'image:https://localhost.com/image.png[Alt text" onerror="alert(7)]',
output: "<div>\n<p><span><img src=\"https://localhost.com/image.png\" alt=\"Alt text\"></span></p>\n</div>"
},
'pre' => {
input: '```mypre"><script>alert(3)</script>',
output: "<div>\n<div>\n<pre lang=\"mypre\">\"&gt;<code></code></pre>\n</div>\n</div>"
}
}
links.each do |name, data|
it "does not convert dangerous #{name} into HTML" do
expect(render(data[:input], context)).to eql data[:output]
end
end
end
end end
def render(*args) def render(*args)
......
require 'spec_helper'
describe Gitlab::OtherMarkup, lib: true do
context "XSS Checks" do
links = {
'links' => {
file: 'file.rdoc',
input: 'XSS[JaVaScriPt:alert(1)]',
output: '<p><a>XSS</a></p>'
}
}
links.each do |name, data|
it "does not convert dangerous #{name} into HTML" do
expect(render(data[:file], data[:input], context)).to eql data[:output]
end
end
end
def render(*args)
described_class.render(*args)
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment