Skip to content
Snippets Groups Projects
Unverified Commit 8baf9c16 authored by Darby Frey's avatar Darby Frey Committed by GitLab
Browse files

Treat a missing fixed_code block as a false positive

Fixes a case where Resolve Vulnerability with AI was returning an error response when it should have been treated as a false positive

Changelog: fixed
MR:
EE: true
parent fd6b8b86
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -74,19 +74,17 @@ def extract_llm_change(ai_response)
raise EmptyResponseError, "Empty response from LLM" if ai_response.blank?
 
content = ai_response.dig('predictions', 0, 'content') || ai_response.dig('content', 0, 'text') || ''
description_options = {}
regex = /(?<=#{Regexp.escape(START_CODE)}).*?(?=#{Regexp.escape(END_CODE)})/mo
 
match_data = content.match(regex)
return [ai_response, false, description_options] unless match_data
return [{ false_positive: true }, false, description_options] if match_data[0].blank?
fixed_code = get_fixed_code(content)
 
description_options = {}
description_options[:analysis_data] = get_analysis_data(content)
description_options[:summary_data] = get_summary_data(content)
 
return [{ false_positive: true }, false, description_options] if false_positive?(content)
return [ai_response, false, description_options] if fixed_code.nil? && ai_response.has_key?('error')
return [{ false_positive: true }, false, description_options] if false_positive?(content, fixed_code)
 
[match_data[0], true, description_options]
[fixed_code, true, description_options]
end
 
def create_merge_request_suggestion(
Loading
Loading
@@ -213,6 +211,13 @@ def vulnerability
resource
end
 
def get_fixed_code(content)
regex = /(?<=#{Regexp.escape(START_CODE)}).*?(?=#{Regexp.escape(END_CODE)})/mo
match_data = content.match(regex)
match_data[0] if match_data
end
def get_analysis_data(content)
analysis_regex = /(?<=#{Regexp.escape(START_ANALYSIS)}).*?(?=#{Regexp.escape(END_ANALYSIS)})/mo
 
Loading
Loading
@@ -227,7 +232,9 @@ def get_summary_data(content)
summary_match_data[0] if summary_match_data
end
 
def false_positive?(content)
def false_positive?(content, fixed_code)
return true if fixed_code.nil? || fixed_code.blank?
is_false_positive_regex = %r{
(?<=#{Regexp.escape(START_IS_FALSE_POSITIVE)})
.*?
Loading
Loading
Loading
Loading
@@ -619,6 +619,40 @@ def execute_resolve(message_params = {}, options = {})
end
end
 
context 'when the LLM responds does not include a code block' do
let(:anthropic_content) do
<<~CONTENT
<analysis>
analysis</analysis>
<is_false_positive>
#{is_false_positive}</is_false_positive>
<summary>
some summary</summary>
CONTENT
end
before do
allow(::Gitlab::Llm::ResolveVulnerability::Client).to receive(:new).and_call_original
allow_next_instance_of(::Gitlab::Llm::ResolveVulnerability::Client) do |client|
allow(client).to receive(:messages_complete).and_return(example_response_anthropic)
end
end
it 'publishes a false positive error to the graphql subscription' do
resolve.execute
expect(GraphqlTriggers).to have_received(:ai_completion_response).with(
an_object_having_attributes(
role: ::Gitlab::Llm::AiMessage::ROLE_ASSISTANT,
request_id: 'uuid',
errors: [a_string_starting_with('The response from the AI provider was ' \
'empty because it has determined this vulnerability to be a false positive.')],
user: user,
resource: vulnerability
))
end
end
context 'when the LLM responds with the is_false_positive tag' do
let(:is_false_positive) { "true" }
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment