diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index eaa2db2e247ef1cc7e631434789de0a50fb5fddf..550d14d4c39d6cdca525c26766da19157ba22413 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -71,8 +71,12 @@ class Milestone < ActiveRecord::Base
   end
 
   def to_reference(from_project = nil)
+    escaped_title = self.title.gsub("]", "\\]")
+
     h = Gitlab::Application.routes.url_helpers
-    h.namespace_project_milestone_url(self.project.namespace, self.project, self)
+    url = h.namespace_project_milestone_url(self.project.namespace, self.project, self)
+
+    "[#{escaped_title}](#{url})"
   end
 
   def reference_link_text(from_project = nil)
diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb
index 302b750aee5f839e0ad045b4393d3868697c8c73..0620096d6890a0c9b8946ae5abcb15413e9ad124 100644
--- a/spec/fixtures/markdown.md.erb
+++ b/spec/fixtures/markdown.md.erb
@@ -219,7 +219,6 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
 - Milestone: <%= milestone.to_reference %>
 - Milestone in another project: <%= xmilestone.to_reference(project) %>
 - Ignored in code: `<%= milestone.to_reference %>`
-- Ignored in links: [Link to <%= milestone.to_reference %>](#milestone-link)
 - Link to milestone by URL: [Milestone](<%= urls.namespace_project_milestone_url(milestone.project.namespace, milestone.project, milestone) %>)
 
 ### Task Lists
diff --git a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
index 86b71210100728455cb531ca318928b6635f7aa3..ebf3d7489b53ad71e44d0055fb3525804d80176b 100644
--- a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
@@ -18,7 +18,9 @@ describe Banzai::Filter::MilestoneReferenceFilter, lib: true do
   end
 
   context 'internal reference' do
-    let(:reference) { milestone.to_reference }
+    # Convert the Markdown link to only the URL, since these tests aren't run through the regular Markdown pipeline.
+    # Milestone reference behavior in the full Markdown pipeline is tested elsewhere.
+    let(:reference) { milestone.to_reference.gsub(/\[([^\]]+)\]\(([^)]+)\)/, '\2') }
 
     it 'links to a valid reference' do
       doc = reference_filter("See #{reference}")