diff --git a/doc/api/vulnerabilities.md b/doc/api/vulnerabilities.md
index cc6e5d3960b0ae2835feb0997f84ade300165d98..eaa4c13de55783560a138f9e8a5e49bb39439d4d 100644
--- a/doc/api/vulnerabilities.md
+++ b/doc/api/vulnerabilities.md
@@ -30,6 +30,7 @@ GET /projects/:id/vulnerabilities?scope=all
 GET /projects/:id/vulnerabilities?scope=dismissed
 GET /projects/:id/vulnerabilities?severity=high
 GET /projects/:id/vulnerabilities?confidence=unknown,experimental
+GET /projects/:id/vulnerabilities?pipeline_id=42
 ```
 
 | Attribute     | Type           | Required | Description                                                                                                                                                                 |
@@ -39,6 +40,7 @@ GET /projects/:id/vulnerabilities?confidence=unknown,experimental
 | `scope`       | string         | no       | Returns vulnerabilities for the given scope: `all` or `dismissed`. Defaults to `dismissed`                                                                                  |
 | `severity`    | string array   | no       | Returns vulnerabilities belonging to specified severity level: `undefined`, `info`, `unknown`, `low`, `medium`, `high`, or `critical`. Defaults to all'                     |
 | `confidence`  | string array   | no       | Returns vulnerabilities belonging to specified confidence level: `undefined`, `ignore`, `unknown`, `experimental`, `low`, `medium`, `high`, or `confirmed`. Defaults to all |
+| `pipeline_id` | integer/string | no       | Returns vulnerabilities belonging to specified pipeline.                                                                                                                    |
 
 ```bash
 curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/vulnerabilities
diff --git a/ee/changelogs/unreleased/rf-optional-pipeline-for-vulnerabilities-api.yml b/ee/changelogs/unreleased/rf-optional-pipeline-for-vulnerabilities-api.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8eb6d9e47392d1bc34e768fbb139b88e5c2060f5
--- /dev/null
+++ b/ee/changelogs/unreleased/rf-optional-pipeline-for-vulnerabilities-api.yml
@@ -0,0 +1,5 @@
+---
+title: 'Add Vulnerabilities API scoping: pipeline'
+merge_request: 14376
+author:
+type: added
diff --git a/ee/lib/api/vulnerabilities.rb b/ee/lib/api/vulnerabilities.rb
index 1017f83fd28c050731487489919c0e6ca3d4501d..3595a491ee466c54afc77a2a28f7fb5a218e8391 100644
--- a/ee/lib/api/vulnerabilities.rb
+++ b/ee/lib/api/vulnerabilities.rb
@@ -6,7 +6,11 @@ module API
 
     helpers do
       def vulnerability_occurrences_by(params)
-        pipeline = params[:project].latest_pipeline_with_security_reports
+        pipeline = if params[:pipeline_id]
+                     params[:project].ci_pipelines.find_by(id: params[:pipeline_id]) # rubocop:disable CodeReuse/ActiveRecord
+                   else
+                     params[:project].latest_pipeline_with_security_reports
+                   end
 
         return [] unless pipeline
 
@@ -38,6 +42,7 @@ module API
                  type: Array[String],
                  desc: 'Returns vulnerabilities belonging to specified confidence level: `undefined`, `ignore`, `unknown`, `experimental`, `low`, `medium`, `high`, or `confirmed`. Defaults to all',
                  default: ::Vulnerabilities::Occurrence.confidences.keys
+        optional :pipeline_id, type: String, desc: 'The ID of the pipeline'
 
         use :pagination
       end
diff --git a/ee/spec/requests/api/vulnerabilities_spec.rb b/ee/spec/requests/api/vulnerabilities_spec.rb
index 8ddef4ae1ced0b9fe1cd7556c2066af55aca7201..6238ba33770e9c1d9cdc0b9eb6a0cdab6c8ed4d4 100644
--- a/ee/spec/requests/api/vulnerabilities_spec.rb
+++ b/ee/spec/requests/api/vulnerabilities_spec.rb
@@ -7,6 +7,7 @@ describe API::Vulnerabilities do
   set(:user) { create(:user) }
 
   let(:pipeline) { create(:ci_empty_pipeline, status: :created, project: project) }
+  let(:pipeline_without_vulnerabilities) { create(:ci_pipeline_without_jobs, status: :created, project: project) }
 
   let(:build_ds) { create(:ci_build, :success, name: 'ds_job', pipeline: pipeline, project: project) }
   let(:build_sast) { create(:ci_build, :success, name: 'sast_job', pipeline: pipeline, project: project) }
@@ -105,6 +106,34 @@ describe API::Vulnerabilities do
 
           expect(json_response.map { |v| v['confidence'] }.uniq).to eq %w[high]
         end
+
+        context 'when pipeline_id is supplied' do
+          it 'returns vulnerabilities from supplied pipeline' do
+            occurrence_count = (sast_report.occurrences.count + ds_report.occurrences.count - 1).to_s
+
+            get api("/projects/#{project.id}/vulnerabilities", user), params: { per_page: 40, pipeline_id: pipeline.id }
+
+            expect(response).to have_gitlab_http_status(200)
+
+            expect(response.headers['X-Total']).to eq occurrence_count
+          end
+
+          context 'pipeline has no reports' do
+            it 'returns empty results' do
+              get api("/projects/#{project.id}/vulnerabilities", user), params: { per_page: 40, pipeline_id: pipeline_without_vulnerabilities.id }
+
+              expect(json_response).to eq []
+            end
+          end
+
+          context 'with unknown pipeline' do
+            it 'returns empty results' do
+              get api("/projects/#{project.id}/vulnerabilities", user), params: { per_page: 40, pipeline_id: 0 }
+
+              expect(json_response).to eq []
+            end
+          end
+        end
       end
     end