Merge branch 'main' into avm99963-monorail

Merged commit 3779da353b36d43cf778e7d4f468097714dd4540

GitOrigin-RevId: 6451a5c6b75afb0fd1f37b3f14521148d0722ea8
diff --git a/static_src/shared/issue-fields.js b/static_src/shared/issue-fields.js
index 09ac7d3..0acbe60 100644
--- a/static_src/shared/issue-fields.js
+++ b/static_src/shared/issue-fields.js
@@ -37,6 +37,13 @@
   PROJECT_TYPE: 'PROJECT_TYPE',
 });
 
+/** @enum {string} */
+export const migratedTypes = Object.freeze({
+  BUGANIZER_TYPE: 'BUGANIZER_TYPE',
+  LAUNCH_TYPE: 'LAUNCH_TYPE',
+  NONE: 'NONE',
+});
+
 const GROUPABLE_FIELD_TYPES = new Set([
   fieldTypes.DATE_TYPE,
   fieldTypes.ENUM_TYPE,
diff --git a/static_src/shared/md-helper.js b/static_src/shared/md-helper.js
index fdceebc..8a22b0d 100644
--- a/static_src/shared/md-helper.js
+++ b/static_src/shared/md-helper.js
@@ -38,7 +38,7 @@
 const SANITIZE_OPTIONS = Object.freeze({
   RETURN_TRUSTED_TYPE: true,
   FORBID_TAGS: ['style'],
-  FORBID_ATTR: ['style', 'autoplay'],
+  FORBID_ATTR: ['style', 'autoplay', 'src'],
 });
 
 /**
@@ -50,31 +50,6 @@
   return raw.replace(/<b>|<\/b>/g, '**');
 };
 
-/** @const {Object} Basic HTML character escape mapping */
-const HTML_ESCAPE_MAP = Object.freeze({
-  '&': '&amp;',
-  '<': '&lt;',
-  '>': '&gt;',
-  '"': '&quot;',
-  '\'': '&#39;',
-  '/': '&#x2F;',
-  '`': '&#x60;',
-  '=': '&#x3D;',
-});
-
-/**
- * Escapes HTML characters, used to render HTML blocks in Markdown. This
- * alleviates security flaws but is not the primary security barrier, that is
- * handled by DOMPurify.
- * @param {string} text Content that looks to Marked parser to contain HTML.
- * @return {string} Same text content after escaping HTML characters.
- */
-const escapeHtml = (text) => {
-  return text.replace(/[<>"']/g, (s) => {
-    return HTML_ESCAPE_MAP[s];
-  });
-};
-
 /**
 * Checks to see if input string is a valid HTTP link.
  * @param {string} string
@@ -139,8 +114,7 @@
   // autolinking.
   // TODO(crbug.com/monorail/9310): Integrate autolink
   const preprocessed = replaceBoldTag(raw);
-  const escaped = escapeHtml(preprocessed);
-  const converted = marked(escaped);
+  const converted = marked(preprocessed);
   const sanitized = DOMPurify.sanitize(converted, SANITIZE_OPTIONS);
   return sanitized.toString();
 };
diff --git a/static_src/shared/md-helper.test.js b/static_src/shared/md-helper.test.js
index 6056849..52ba279 100644
--- a/static_src/shared/md-helper.test.js
+++ b/static_src/shared/md-helper.test.js
@@ -104,22 +104,8 @@
     assert.equal(actual, expected);
   });
 
-  it('escapes HTML content', () => {
-    let actual = renderMarkdown('<input></input>');
-    assert.equal(actual, '<p>&lt;input&gt;&lt;/input&gt;</p>\n');
-
-    actual = renderMarkdown('<a href="https://google.com">clickme</a>');
-    assert.equal(actual,
-      `<p>&lt;a href="<span class="annotated-link"><a title="" ` +
-      `href="https://google.com&quot;>clickme</a"><span ` +
-      `class="material-icons link_off">link_off</span>` +
-      `https://google.com"&gt;clickme&lt;/a</a><span ` +
-      `class="tooltip">Link may be malformed: ` +
-      `https://google.com"&gt;clickme&lt;/a</span></span>&gt;</p>\n`);
-  });
-
-  it('escapes video content', () => {
-    const actual = renderMarkdown('<video src="//youtube" control></video>');
-    assert.equal(actual, '<p>&lt;video src="//youtube" control&gt;&lt;/video&gt;</p>\n');
+  it('forbids src', () => {
+    const actual = renderMarkdown('<video id="foo" src="//youtube" control></video>');
+    assert.equal(actual, '<p><video id="foo"></video></p>\n');
   });
 });