diff --git a/app/builders/messages/messenger/message_builder.rb b/app/builders/messages/messenger/message_builder.rb index 2a2dff043..4500ca705 100644 --- a/app/builders/messages/messenger/message_builder.rb +++ b/app/builders/messages/messenger/message_builder.rb @@ -28,7 +28,6 @@ class Messages::Messenger::MessageBuilder def attach_file(attachment, file_url) SafeFetch.fetch( file_url, - allowed_content_type_prefixes: %w[image/ video/ audio/], allowed_content_types: Attachment::ACCEPTABLE_FILE_TYPES ) do |attachment_file| attachment.file.attach( diff --git a/app/services/sms/incoming_message_service.rb b/app/services/sms/incoming_message_service.rb index fc6ba77b8..791699a6a 100644 --- a/app/services/sms/incoming_message_service.rb +++ b/app/services/sms/incoming_message_service.rb @@ -101,7 +101,6 @@ class Sms::IncomingMessageService SafeFetch.fetch( media_url, http_basic_authentication: [channel.provider_config['api_key'], channel.provider_config['api_secret']], - allowed_content_type_prefixes: %w[image/ video/ audio/], allowed_content_types: Attachment::ACCEPTABLE_FILE_TYPES, & ) diff --git a/app/services/telegram/incoming_message_service.rb b/app/services/telegram/incoming_message_service.rb index 89718a1ac..6ba0b2d37 100644 --- a/app/services/telegram/incoming_message_service.rb +++ b/app/services/telegram/incoming_message_service.rb @@ -150,7 +150,6 @@ class Telegram::IncomingMessageService SafeFetch.fetch( file_download_path, - allowed_content_type_prefixes: %w[image/ video/ audio/], allowed_content_types: Attachment::ACCEPTABLE_FILE_TYPES ) do |attachment_file| build_file_attachment(attachment_file) diff --git a/app/services/twilio/incoming_message_service.rb b/app/services/twilio/incoming_message_service.rb index 6ef1ccf45..7981558b2 100644 --- a/app/services/twilio/incoming_message_service.rb +++ b/app/services/twilio/incoming_message_service.rb @@ -175,7 +175,6 @@ class Twilio::IncomingMessageService SafeFetch.fetch( media_url, http_basic_authentication: auth_credentials, - allowed_content_type_prefixes: %w[image/ video/ audio/], allowed_content_types: Attachment::ACCEPTABLE_FILE_TYPES, & ) @@ -185,7 +184,6 @@ class Twilio::IncomingMessageService Rails.logger.info "Error downloading attachment from Twilio: #{error.message}: Retrying without auth" SafeFetch.fetch( media_url, - allowed_content_type_prefixes: %w[image/ video/ audio/], allowed_content_types: Attachment::ACCEPTABLE_FILE_TYPES, & ) diff --git a/app/services/whatsapp/incoming_message_service_helpers.rb b/app/services/whatsapp/incoming_message_service_helpers.rb index cc28d1b31..217767221 100644 --- a/app/services/whatsapp/incoming_message_service_helpers.rb +++ b/app/services/whatsapp/incoming_message_service_helpers.rb @@ -3,7 +3,6 @@ module Whatsapp::IncomingMessageServiceHelpers SafeFetch.fetch( inbox.channel.media_url(attachment_payload[:id]), headers: inbox.channel.api_headers, - allowed_content_type_prefixes: %w[image/ video/ audio/], allowed_content_types: Attachment::ACCEPTABLE_FILE_TYPES, & ) diff --git a/app/services/whatsapp/incoming_message_whatsapp_cloud_service.rb b/app/services/whatsapp/incoming_message_whatsapp_cloud_service.rb index e93dbc26f..7d13a284a 100644 --- a/app/services/whatsapp/incoming_message_whatsapp_cloud_service.rb +++ b/app/services/whatsapp/incoming_message_whatsapp_cloud_service.rb @@ -20,7 +20,6 @@ class Whatsapp::IncomingMessageWhatsappCloudService < Whatsapp::IncomingMessageB SafeFetch.fetch( url_response.parsed_response['url'], headers: inbox.channel.api_headers, - allowed_content_type_prefixes: %w[image/ video/ audio/], allowed_content_types: Attachment::ACCEPTABLE_FILE_TYPES, & ) diff --git a/lib/safe_fetch.rb b/lib/safe_fetch.rb index e82f63d76..6a0c26542 100644 --- a/lib/safe_fetch.rb +++ b/lib/safe_fetch.rb @@ -2,8 +2,26 @@ require 'ssrf_filter' # rubocop:disable Metrics/ModuleLength module SafeFetch - DEFAULT_ALLOWED_CONTENT_TYPE_PREFIXES = %w[image/ video/].freeze - DEFAULT_ALLOWED_CONTENT_TYPES = [].freeze + DEFAULT_ALLOWED_CONTENT_TYPE_PREFIXES = %w[image/ video/ audio/].freeze + DEFAULT_ALLOWED_CONTENT_TYPES = %w[ + text/csv + text/plain + text/rtf + application/json + application/pdf + application/zip + application/x-7z-compressed + application/vnd.rar + application/x-tar + application/msword + application/vnd.ms-excel + application/vnd.ms-powerpoint + application/rtf + application/vnd.oasis.opendocument.text + application/vnd.openxmlformats-officedocument.presentationml.presentation + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + application/vnd.openxmlformats-officedocument.wordprocessingml.document + ].freeze DEFAULT_SENSITIVE_HEADERS = %w[authorization cookie].freeze DEFAULT_OPEN_TIMEOUT = 2 DEFAULT_READ_TIMEOUT = 20 diff --git a/spec/lib/safe_fetch_spec.rb b/spec/lib/safe_fetch_spec.rb index 012dd09cf..df5e521c1 100644 --- a/spec/lib/safe_fetch_spec.rb +++ b/spec/lib/safe_fetch_spec.rb @@ -195,6 +195,46 @@ RSpec.describe SafeFetch do expect { described_class.fetch(url) { nil } }.not_to raise_error end + it 'allows audio/mpeg responses' do + stub_request(:get, url).to_return( + status: 200, + body: File.new(Rails.root.join('spec/assets/sample.mp3')), + headers: { 'Content-Type' => 'audio/mpeg' } + ) + + expect { described_class.fetch(url) { nil } }.not_to raise_error + end + + it 'allows application/pdf responses' do + stub_request(:get, url).to_return( + status: 200, + body: File.new(Rails.root.join('spec/assets/sample.pdf')), + headers: { 'Content-Type' => 'application/pdf' } + ) + + expect { described_class.fetch(url) { nil } }.not_to raise_error + end + + it 'allows text/plain responses' do + stub_request(:get, url).to_return( + status: 200, + body: 'plain-text', + headers: { 'Content-Type' => 'text/plain' } + ) + + expect { described_class.fetch(url) { nil } }.not_to raise_error + end + + it 'allows text/csv responses' do + stub_request(:get, url).to_return( + status: 200, + body: "id,name\n1,Chatwoot\n", + headers: { 'Content-Type' => 'text/csv' } + ) + + expect { described_class.fetch(url) { nil } }.not_to raise_error + end + it 'strips charset/boundary parameters before comparing' do stub_request(:get, url).to_return( status: 200,