SECURITY: Place a SSRF protection when calling services from the plugin. (#485)
The Faraday adapter and `FinalDestionation::HTTP` will protect us from admin-initiated SSRF attacks when interacting with the external services powering this plugin features.:
This commit is contained in:
parent
1f74a77e17
commit
a65c4076a6
|
@ -69,7 +69,7 @@ module DiscourseAi
|
||||||
|
|
||||||
prompt = dialect.translate
|
prompt = dialect.translate
|
||||||
|
|
||||||
Net::HTTP.start(
|
FinalDestination::HTTP.start(
|
||||||
model_uri.host,
|
model_uri.host,
|
||||||
model_uri.port,
|
model_uri.port,
|
||||||
use_ssl: true,
|
use_ssl: true,
|
||||||
|
|
|
@ -14,7 +14,8 @@ module ::DiscourseAi
|
||||||
|
|
||||||
endpoint = "#{base_url}#{model}"
|
endpoint = "#{base_url}#{model}"
|
||||||
|
|
||||||
response = Faraday.post(endpoint, content.to_json, headers)
|
conn = Faraday.new { |f| f.adapter FinalDestination::FaradayAdapter }
|
||||||
|
response = conn.post(endpoint, content.to_json, headers)
|
||||||
|
|
||||||
raise Net::HTTPBadResponse if ![200].include?(response.status)
|
raise Net::HTTPBadResponse if ![200].include?(response.status)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@ module ::DiscourseAi
|
||||||
|
|
||||||
headers["X-API-KEY"] = api_key if api_key.present?
|
headers["X-API-KEY"] = api_key if api_key.present?
|
||||||
|
|
||||||
response = Faraday.post(endpoint, { model: model, content: content }.to_json, headers)
|
conn = Faraday.new { |f| f.adapter FinalDestination::FaradayAdapter }
|
||||||
|
response = conn.post(endpoint, { model: model, content: content }.to_json, headers)
|
||||||
|
|
||||||
raise Net::HTTPBadResponse if ![200, 415].include?(response.status)
|
raise Net::HTTPBadResponse if ![200, 415].include?(response.status)
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,9 @@ module ::DiscourseAi
|
||||||
|
|
||||||
headers["X-API-KEY"] = api_key if api_key.present?
|
headers["X-API-KEY"] = api_key if api_key.present?
|
||||||
|
|
||||||
|
conn = Faraday.new { |f| f.adapter FinalDestination::FaradayAdapter }
|
||||||
response =
|
response =
|
||||||
Faraday.post(
|
conn.post(
|
||||||
endpoint,
|
endpoint,
|
||||||
{ model: model, content: content, candidates: candidates }.to_json,
|
{ model: model, content: content, candidates: candidates }.to_json,
|
||||||
headers,
|
headers,
|
||||||
|
|
|
@ -11,7 +11,8 @@ module ::DiscourseAi
|
||||||
|
|
||||||
body = { content: { parts: [{ text: content }] } }
|
body = { content: { parts: [{ text: content }] } }
|
||||||
|
|
||||||
response = Faraday.post(url, body.to_json, headers)
|
conn = Faraday.new { |f| f.adapter FinalDestination::FaradayAdapter }
|
||||||
|
response = conn.post(url, body.to_json, headers)
|
||||||
|
|
||||||
raise Net::HTTPBadResponse if ![200].include?(response.status)
|
raise Net::HTTPBadResponse if ![200].include?(response.status)
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@ module ::DiscourseAi
|
||||||
headers["X-API-KEY"] = SiteSetting.ai_hugging_face_tei_api_key
|
headers["X-API-KEY"] = SiteSetting.ai_hugging_face_tei_api_key
|
||||||
end
|
end
|
||||||
|
|
||||||
response = Faraday.post(api_endpoint, body, headers)
|
conn = Faraday.new { |f| f.adapter FinalDestination::FaradayAdapter }
|
||||||
|
response = conn.post(api_endpoint, body, headers)
|
||||||
|
|
||||||
raise Net::HTTPBadResponse if ![200].include?(response.status)
|
raise Net::HTTPBadResponse if ![200].include?(response.status)
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ module ::DiscourseAi
|
||||||
payload = { model: model, input: content }
|
payload = { model: model, input: content }
|
||||||
payload[:dimensions] = dimensions if dimensions.present?
|
payload[:dimensions] = dimensions if dimensions.present?
|
||||||
|
|
||||||
response = Faraday.post(SiteSetting.ai_openai_embeddings_url, payload.to_json, headers)
|
conn = Faraday.new { |f| f.adapter FinalDestination::FaradayAdapter }
|
||||||
|
response = conn.post(SiteSetting.ai_openai_embeddings_url, payload.to_json, headers)
|
||||||
|
|
||||||
case response.status
|
case response.status
|
||||||
when 200
|
when 200
|
||||||
|
|
|
@ -28,7 +28,7 @@ module ::DiscourseAi
|
||||||
response_format: "b64_json",
|
response_format: "b64_json",
|
||||||
}
|
}
|
||||||
|
|
||||||
Net::HTTP.start(
|
FinalDestination::HTTP.start(
|
||||||
uri.host,
|
uri.host,
|
||||||
uri.port,
|
uri.port,
|
||||||
use_ssl: uri.scheme == "https",
|
use_ssl: uri.scheme == "https",
|
||||||
|
|
|
@ -57,7 +57,8 @@ module ::DiscourseAi
|
||||||
|
|
||||||
endpoint = "v1/generation/#{engine}/text-to-image"
|
endpoint = "v1/generation/#{engine}/text-to-image"
|
||||||
|
|
||||||
response = Faraday.post("#{api_url}/#{endpoint}", payload.to_json, headers)
|
conn = Faraday.new { |f| f.adapter FinalDestination::FaradayAdapter }
|
||||||
|
response = conn.post("#{api_url}/#{endpoint}", payload.to_json, headers)
|
||||||
|
|
||||||
if response.status != 200
|
if response.status != 200
|
||||||
Rails.logger.error(
|
Rails.logger.error(
|
||||||
|
|
|
@ -99,13 +99,13 @@ class EndpointMock
|
||||||
|
|
||||||
def with_chunk_array_support
|
def with_chunk_array_support
|
||||||
mock = mocked_http
|
mock = mocked_http
|
||||||
@original_net_http = ::Net.send(:remove_const, :HTTP)
|
@original_net_http = ::FinalDestination.send(:remove_const, :HTTP)
|
||||||
::Net.send(:const_set, :HTTP, mock)
|
::FinalDestination.send(:const_set, :HTTP, mock)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
ensure
|
ensure
|
||||||
::Net.send(:remove_const, :HTTP)
|
::FinalDestination.send(:remove_const, :HTTP)
|
||||||
::Net.send(:const_set, :HTTP, @original_net_http)
|
::FinalDestination.send(:const_set, :HTTP, @original_net_http)
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
@ -113,7 +113,7 @@ class EndpointMock
|
||||||
# Copied from https://github.com/bblimke/webmock/issues/629
|
# Copied from https://github.com/bblimke/webmock/issues/629
|
||||||
# Workaround for stubbing a streamed response
|
# Workaround for stubbing a streamed response
|
||||||
def mocked_http
|
def mocked_http
|
||||||
Class.new(::Net::HTTP) do
|
Class.new(FinalDestination::HTTP) do
|
||||||
def request(*)
|
def request(*)
|
||||||
super do |response|
|
super do |response|
|
||||||
response.instance_eval do
|
response.instance_eval do
|
||||||
|
|
Loading…
Reference in New Issue