diff --git a/ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_details_graphql/index.stories.js b/ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_details_graphql/index.stories.js
index c3b64fd09aca5ce521e8bdeae6f0614999ec4938..33c53a9fad7886f366b71c6ebe5d472e2b03753e 100644
--- a/ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_details_graphql/index.stories.js
+++ b/ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_details_graphql/index.stories.js
@@ -27,4 +27,10 @@ Default.args = {
     name: 'GitLab.com',
     webUrl: 'http://gitlab.com',
   },
+  location: {
+    file: '/src/js/main.js',
+    blobPath: '/project/namespace/-/blob/e3343434/src/js/main.js',
+    startLine: '10',
+    endLine: '20',
+  },
 };
diff --git a/ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_details_graphql/index.vue b/ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_details_graphql/index.vue
index ee64b594dada61bc6ae395b126df586e1b83aa0b..d71bd981cc45c9e703dc46598ef29872506a6531 100644
--- a/ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_details_graphql/index.vue
+++ b/ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_details_graphql/index.vue
@@ -11,6 +11,8 @@ export default {
     descriptionSectionHeading: s__('Vulnerability|Description'),
     severityLabel: s__('Vulnerability|Severity:'),
     projectLabel: s__('Vulnerability|Project:'),
+    locationHeading: s__('Vulnerability|Location'),
+    locationFileLabel: s__('Vulnerability|File:'),
   },
   components: {
     GlLink,
@@ -51,6 +53,32 @@ export default {
       type: Object,
       required: true,
     },
+    /**
+     * Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability.
+     *
+     * @typedef {{ startLine?: string, endLine?: string, blobPath?: string, file?: string }} VulnerabilityLocationSast
+     * @typedef {( VulnerabilityLocationSast | null )} VulnerabilityLocation
+     * @type VulnerabilityLocation
+     */
+    location: {
+      type: Object,
+      required: false,
+      default: null,
+    },
+  },
+  computed: {
+    file() {
+      const { startLine, endLine, blobPath, file } = this.location;
+
+      const lineNumber = endLine > startLine ? `${startLine}-${endLine}` : startLine;
+      const url = `${blobPath}#L${lineNumber}`;
+      const name = `${file}:${lineNumber}`;
+
+      return {
+        url,
+        name,
+      };
+    },
   },
 };
 </script>
@@ -64,7 +92,7 @@ export default {
       <p>{{ description }}</p>
     </details-section>
 
-    <details-section>
+    <details-section data-testid="main-section">
       <template #list>
         <details-section-list-item
           :label="$options.i18n.severityLabel"
@@ -80,5 +108,21 @@ export default {
         </details-section-list-item>
       </template>
     </details-section>
+
+    <details-section
+      v-if="location"
+      :heading="$options.i18n.locationHeading"
+      data-testid="location-section"
+    >
+      <template #list>
+        <details-section-list-item
+          v-if="location.file"
+          :label="$options.i18n.locationFileLabel"
+          data-testid="location-file-list-item"
+        >
+          <gl-link :href="file.url">{{ file.name }}</gl-link>
+        </details-section-list-item>
+      </template>
+    </details-section>
   </article>
 </template>
diff --git a/ee/spec/frontend/security_dashboard/components/shared/vulnerability_details_graphql/index_spec.js b/ee/spec/frontend/security_dashboard/components/shared/vulnerability_details_graphql/index_spec.js
index 5b6923d158dda295292ff0bcf692f4a53c3f6b23..5e078c6a0d757e84ca27547f0092c83089c3072b 100644
--- a/ee/spec/frontend/security_dashboard/components/shared/vulnerability_details_graphql/index_spec.js
+++ b/ee/spec/frontend/security_dashboard/components/shared/vulnerability_details_graphql/index_spec.js
@@ -17,7 +17,7 @@ const TEST_VULNERABILITY = {
 describe('ee/security_dashboard/components/shared/vulnerability_details_graphql/index.vue', () => {
   let wrapper;
 
-  const createComponent = () => {
+  const createComponent = (options = {}) => {
     wrapper = shallowMountExtended(Details, {
       propsData: {
         ...TEST_VULNERABILITY,
@@ -27,25 +27,26 @@ describe('ee/security_dashboard/components/shared/vulnerability_details_graphql/
         DetailsSection,
         DetailsSectionListItem,
       },
+      ...options,
     });
   };
 
+  const expectToBeDetailsSection = (sectionWrapper, { heading = '' } = {}) => {
+    expect(sectionWrapper.is(DetailsSection)).toBe(true);
+    expect(sectionWrapper.props('heading')).toBe(heading);
+  };
+
   afterEach(() => {
     wrapper.destroy();
   });
 
-  beforeEach(createComponent);
-
   describe('description section', () => {
-    const findDescriptionSection = () => wrapper.findByTestId('description-section');
+    beforeEach(createComponent);
 
-    it('is a details-section with the correct heading', () => {
-      const descriptionSection = findDescriptionSection();
+    const findDescriptionSection = () => wrapper.findByTestId('description-section');
 
-      expect(descriptionSection.is(DetailsSection)).toBe(true);
-      expect(descriptionSection.props()).toMatchObject({
-        heading: 'Description',
-      });
+    it('is a details section with the correct heading', () => {
+      expectToBeDetailsSection(findDescriptionSection(), { heading: 'Description' });
     });
 
     it(`contains the vulnerability's description`, () => {
@@ -53,19 +54,83 @@ describe('ee/security_dashboard/components/shared/vulnerability_details_graphql/
     });
   });
 
-  it('renders the severity with a badge', () => {
-    const severity = wrapper.findByTestId('severity-list-item');
+  describe('main section', () => {
+    beforeEach(createComponent);
+
+    it('is a details section', () => {
+      expectToBeDetailsSection(wrapper.findByTestId('main-section'));
+    });
+
+    it('renders the severity with a badge', () => {
+      const severity = wrapper.findByTestId('severity-list-item');
+
+      expect(severity.text()).toContain('Severity:');
+      expect(severity.findComponent(SeverityBadge).exists()).toBe(true);
+    });
+
+    it('renders the project with a link to it', () => {
+      const project = wrapper.findByTestId('project-list-item');
 
-    expect(severity.text()).toContain('Severity:');
-    expect(severity.findComponent(SeverityBadge).exists()).toBe(true);
+      expect(project.text()).toContain('Project:');
+      expect(project.findComponent(GlLink).attributes('href')).toBe(
+        TEST_VULNERABILITY.project.webUrl,
+      );
+    });
   });
 
-  it('renders the project with a link to it', () => {
-    const project = wrapper.findByTestId('project-list-item');
+  describe('location section', () => {
+    const findLocationSection = () => wrapper.findByTestId('location-section');
+
+    describe('with no location data', () => {
+      beforeEach(createComponent);
+
+      it('does not get rendered', () => {
+        expect(findLocationSection().exists()).toBe(false);
+      });
+    });
+
+    describe('with location data', () => {
+      beforeEach(() =>
+        createComponent({
+          propsData: {
+            ...TEST_VULNERABILITY,
+            location: {},
+          },
+        }),
+      );
 
-    expect(project.text()).toContain('Project:');
-    expect(project.findComponent(GlLink).attributes('href')).toBe(
-      TEST_VULNERABILITY.project.webUrl,
-    );
+      it('is a details section with the correct heading', () => {
+        expectToBeDetailsSection(findLocationSection(), { heading: 'Location' });
+      });
+
+      describe('with file information', () => {
+        it.each`
+          description                          | lineData                        | expectedLineRange
+          ${'end line is after start line'}    | ${{ startLine: 0, endLine: 1 }} | ${'0-1'}
+          ${'end line is equal to start line'} | ${{ startLine: 1, endLine: 1 }} | ${'1'}
+        `(
+          `links to the vulnerable file's line range "$expectedLineRange" when $description`,
+          ({ lineData, expectedLineRange }) => {
+            const location = {
+              blobPath: '/project/namespace/-/blob/e3343434/src/js/main.js',
+              file: '/src/js/main.js',
+              ...lineData,
+            };
+            createComponent({
+              propsData: {
+                ...TEST_VULNERABILITY,
+                location,
+              },
+            });
+
+            const { blobPath, file } = location;
+            const fileLink = wrapper.findByTestId('location-file-list-item').find(GlLink);
+
+            expect(fileLink.attributes('href')).toBe(`${blobPath}#L${expectedLineRange}`);
+            expect(fileLink.text()).toBe(`${file}:${expectedLineRange}`);
+          },
+        );
+      });
+    });
   });
 });
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8118c4b705daa67f7f29aa5aa7a00a255e723f46..3f8811989e899be9eec6fb65256b37a70972e4fd 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -44263,6 +44263,9 @@ msgstr ""
 msgid "Vulnerability|File"
 msgstr ""
 
+msgid "Vulnerability|File:"
+msgstr ""
+
 msgid "Vulnerability|GitLab Security Report"
 msgstr ""
 
@@ -44287,6 +44290,9 @@ msgstr ""
 msgid "Vulnerability|Links"
 msgstr ""
 
+msgid "Vulnerability|Location"
+msgstr ""
+
 msgid "Vulnerability|Method"
 msgstr ""