diff --git a/db/migrate/20210323155010_populate_dismissal_information_for_vulnerabilities.rb b/db/migrate/20210323155010_populate_dismissal_information_for_vulnerabilities.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aee6d5484d58e51e9178504c2b09e89b6e1c20cb
--- /dev/null
+++ b/db/migrate/20210323155010_populate_dismissal_information_for_vulnerabilities.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class PopulateDismissalInformationForVulnerabilities < ActiveRecord::Migration[6.0]
+  DOWNTIME = false
+  BATCH_SIZE = 100
+  UPDATE_QUERY = <<~SQL
+    UPDATE
+      vulnerabilities
+    SET
+      dismissed_at = COALESCE(dismissed_at, updated_at),
+      dismissed_by_id = COALESCE(dismissed_by_id, updated_by_id, last_edited_by_id, author_id)
+    WHERE
+      vulnerabilities.id IN (%{ids})
+  SQL
+
+  class Vulnerability < ActiveRecord::Base
+    include EachBatch
+
+    self.table_name = 'vulnerabilities'
+
+    enum state: { detected: 1, confirmed: 4, resolved: 3, dismissed: 2 }
+
+    scope :broken, -> { dismissed.where('dismissed_at IS NULL OR dismissed_by_id IS NULL') }
+  end
+
+  def up
+    Vulnerability.broken.each_batch(of: BATCH_SIZE) do |batch|
+      query = format(UPDATE_QUERY, ids: batch.select(:id).to_sql)
+
+      connection.execute(query)
+    end
+  end
+
+  def down
+    # no-op
+  end
+end
diff --git a/db/schema_migrations/20210323155010 b/db/schema_migrations/20210323155010
new file mode 100644
index 0000000000000000000000000000000000000000..23225216b5a7158e0269e911cc1bc8995144ee91
--- /dev/null
+++ b/db/schema_migrations/20210323155010
@@ -0,0 +1 @@
+1143241b1a8d1554c86a8d72d43276fa15c0193e510f47d5d7c64769860c60e3
\ No newline at end of file
diff --git a/spec/migrations/populate_dismissal_information_for_vulnerabilities_spec.rb b/spec/migrations/populate_dismissal_information_for_vulnerabilities_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1db5278195682a6ccc6095af8330579e3a7f1624
--- /dev/null
+++ b/spec/migrations/populate_dismissal_information_for_vulnerabilities_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe PopulateDismissalInformationForVulnerabilities do
+  let(:users) { table(:users) }
+  let(:namespaces) { table(:namespaces) }
+  let(:projects) { table(:projects) }
+  let(:vulnerabilities) { table(:vulnerabilities) }
+
+  let(:existing_dismissed_at) { Time.now }
+  let(:states) { { detected: 1, dismissed: 2, resolved: 3, confirmed: 4 } }
+  let!(:namespace) { namespaces.create!(name: "foo", path: "bar") }
+  let!(:user_1) { users.create!(name: 'John Doe', email: 'john_doe+1@example.com', projects_limit: 5) }
+  let!(:user_2) { users.create!(name: 'John Doe', email: 'john_doe+2@example.com', projects_limit: 5) }
+  let!(:project) { projects.create!(namespace_id: namespace.id) }
+  let!(:vulnerability_params) do
+    {
+      project_id: project.id,
+      author_id: user_1.id,
+      title: 'Vulnerability',
+      severity: 5,
+      confidence: 5,
+      report_type: 5
+    }
+  end
+
+  let!(:detected_vulnerability) { vulnerabilities.create!(**vulnerability_params, state: states[:detected]) }
+  let!(:resolved_vulnerability) { vulnerabilities.create!(**vulnerability_params, state: states[:resolved]) }
+  let!(:confirmed_vulnerability) { vulnerabilities.create!(**vulnerability_params, state: states[:confirmed]) }
+
+  let!(:dismissed_vulnerability_1) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], updated_by_id: user_2.id) }
+  let!(:dismissed_vulnerability_2) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], last_edited_by_id: user_2.id) }
+  let!(:dismissed_vulnerability_3) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], dismissed_at: existing_dismissed_at, author_id: user_2.id) }
+  let!(:dismissed_vulnerability_4) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], dismissed_by_id: user_1.id, author_id: user_2.id) }
+  let!(:dismissed_vulnerability_5) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], dismissed_at: existing_dismissed_at, dismissed_by_id: user_1.id, updated_by_id: user_2.id) }
+
+  around do |example|
+    freeze_time { example.run }
+  end
+
+  it 'updates the dismissal information for vulnerabilities' do
+    expect { migrate! }.to change { dismissed_vulnerability_1.reload.dismissed_at }.from(nil).to(dismissed_vulnerability_1.updated_at)
+                       .and change { dismissed_vulnerability_1.reload.dismissed_by_id }.from(nil).to(user_2.id)
+                       .and change { dismissed_vulnerability_2.reload.dismissed_at }.from(nil).to(dismissed_vulnerability_2.updated_at)
+                       .and change { dismissed_vulnerability_2.reload.dismissed_by_id }.from(nil).to(user_2.id)
+                       .and change { dismissed_vulnerability_3.reload.dismissed_by_id }.from(nil).to(user_2.id)
+                       .and change { dismissed_vulnerability_4.reload.dismissed_at }.from(nil).to(dismissed_vulnerability_4.updated_at)
+                       .and not_change { dismissed_vulnerability_3.reload.dismissed_at }.from(existing_dismissed_at)
+                       .and not_change { dismissed_vulnerability_4.reload.dismissed_by_id }.from(user_1.id)
+                       .and not_change { dismissed_vulnerability_5.reload.dismissed_at }.from(existing_dismissed_at)
+                       .and not_change { dismissed_vulnerability_5.reload.dismissed_by_id }.from(user_1.id)
+                       .and not_change { detected_vulnerability.reload.dismissed_at }.from(nil)
+                       .and not_change { detected_vulnerability.reload.dismissed_by_id }.from(nil)
+                       .and not_change { resolved_vulnerability.reload.dismissed_at }.from(nil)
+                       .and not_change { resolved_vulnerability.reload.dismissed_by_id }.from(nil)
+                       .and not_change { confirmed_vulnerability.reload.dismissed_at }.from(nil)
+                       .and not_change { confirmed_vulnerability.reload.dismissed_by_id }.from(nil)
+  end
+end