diff --git a/app/assets/javascripts/content_editor/extensions/task_item.js b/app/assets/javascripts/content_editor/extensions/task_item.js
index 849fd55034e468c231c5c32200f4ef12714eb1fb..1e19878be9b070df0b3c2cccf24eecd8d0ac4eab 100644
--- a/app/assets/javascripts/content_editor/extensions/task_item.js
+++ b/app/assets/javascripts/content_editor/extensions/task_item.js
@@ -19,9 +19,17 @@ export default TaskItem.extend({
 
           return checkbox?.checked;
         },
-        renderHTML: (attributes) => ({
-          'data-checked': attributes.checked,
-        }),
+        renderHTML: (attributes) => attributes.checked && { 'data-checked': true },
+        keepOnSplit: false,
+      },
+      inapplicable: {
+        default: false,
+        parseHTML: (element) => {
+          const checkbox = element.querySelector('input[type=checkbox].task-list-item-checkbox');
+
+          return typeof checkbox?.dataset.inapplicable !== 'undefined';
+        },
+        renderHTML: (attributes) => attributes.inapplicable && { 'data-inapplicable': true },
         keepOnSplit: false,
       },
     };
@@ -33,6 +41,24 @@ export default TaskItem.extend({
         tag: 'li.task-list-item',
         priority: PARSE_HTML_PRIORITY_HIGHEST,
       },
+      {
+        tag: 'li.task-list-item.inapplicable s',
+        skip: true,
+        priority: PARSE_HTML_PRIORITY_HIGHEST,
+      },
     ];
   },
+
+  addNodeView() {
+    const nodeView = this.parent?.();
+    return ({ node, ...args }) => {
+      const nodeViewInstance = nodeView({ node, ...args });
+
+      if (node.attrs.inapplicable) {
+        nodeViewInstance.dom.querySelector('input[type=checkbox]').disabled = true;
+      }
+
+      return nodeViewInstance;
+    };
+  },
 });
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
index 972b4acf523e2fbee802418d4cec9cc6fd569fac..3b759de57f2c7c39650df171f9cbfb5e5a991847 100644
--- a/app/assets/javascripts/content_editor/services/markdown_serializer.js
+++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js
@@ -228,7 +228,11 @@ const defaultSerializerConfig = {
     [TableHeader.name]: renderTableCell,
     [TableRow.name]: renderTableRow,
     [TaskItem.name]: preserveUnchanged((state, node) => {
-      state.write(`[${node.attrs.checked ? 'x' : ' '}] `);
+      let symbol = ' ';
+      if (node.attrs.inapplicable) symbol = '~';
+      else if (node.attrs.checked) symbol = 'x';
+
+      state.write(`[${symbol}] `);
       if (!node.textContent) state.write(' ');
       state.renderContent(node);
     }),
diff --git a/app/assets/stylesheets/components/content_editor.scss b/app/assets/stylesheets/components/content_editor.scss
index 97f2add4e7771947259d1b2b2d9673d63f84ac4a..f412926ca02b5263e10de58535f4b5eb557ea19d 100644
--- a/app/assets/stylesheets/components/content_editor.scss
+++ b/app/assets/stylesheets/components/content_editor.scss
@@ -149,6 +149,11 @@
         padding: $gl-spacing-scale-1 $gl-spacing-scale-3 0 0;
         margin: 0;
       }
+
+      &[data-inapplicable] * {
+        text-decoration: line-through;
+        color: $gl-text-color-disabled;
+      }
     }
   }
 
diff --git a/glfm_specification/output_example_snapshots/html.yml b/glfm_specification/output_example_snapshots/html.yml
index ca51c26a760bfebbed0ab4ac2a55d66807754ff8..de8467b318839256f9e2fe188ae6a9ad31950dbf 100644
--- a/glfm_specification/output_example_snapshots/html.yml
+++ b/glfm_specification/output_example_snapshots/html.yml
@@ -7639,7 +7639,7 @@
     <task-button></task-button><input type="checkbox" class="task-list-item-checkbox" disabled> incomplete</li>
     </ul>
   wysiwyg: |-
-    <ul dir="auto" start="1" parens="false" bullet="*" data-type="taskList"><li dir="auto" data-checked="false" data-type="taskItem"><label><input type="checkbox"><span></span></label><div><p dir="auto">incomplete</p></div></li></ul>
+    <ul dir="auto" start="1" parens="false" bullet="*" data-type="taskList"><li dir="auto" data-type="taskItem"><label><input type="checkbox"><span></span></label><div><p dir="auto">incomplete</p></div></li></ul>
 07_01_00__gitlab_official_specification_markdown__task_list_items__002:
   canonical: |
     <ul>
@@ -8477,7 +8477,7 @@
     <task-button></task-button><input type="checkbox" class="task-list-item-checkbox" disabled> example</li>
     </ol>
   wysiwyg: |-
-    <ol dir="auto" start="1" parens="false" bullet="*" data-type="taskList"><li dir="auto" data-checked="true" data-type="taskItem"><label><input type="checkbox" checked="checked"><span></span></label><div><p dir="auto">hello</p></div></li><li dir="auto" data-checked="true" data-type="taskItem"><label><input type="checkbox" checked="checked"><span></span></label><div><p dir="auto">world</p></div></li><li dir="auto" data-checked="false" data-type="taskItem"><label><input type="checkbox"><span></span></label><div><p dir="auto">example</p></div></li></ol>
+    <ol dir="auto" start="1" parens="false" bullet="*" data-type="taskList"><li dir="auto" data-checked="true" data-type="taskItem"><label><input type="checkbox" checked="checked"><span></span></label><div><p dir="auto">hello</p></div></li><li dir="auto" data-checked="true" data-type="taskItem"><label><input type="checkbox" checked="checked"><span></span></label><div><p dir="auto">world</p></div></li><li dir="auto" data-type="taskItem"><label><input type="checkbox"><span></span></label><div><p dir="auto">example</p></div></li></ol>
 08_04_46__gitlab_internal_extension_markdown__migrated_golden_master_examples__reference_for_project_wiki__001:
   canonical: |
     TODO: Write canonical HTML for this example
@@ -8828,7 +8828,7 @@
     <task-button></task-button><input type="checkbox" class="task-list-item-checkbox" checked disabled> bar</li>
     </ul>
   wysiwyg: |-
-    <ul dir="auto" start="1" parens="false" bullet="*" data-type="taskList"><li dir="auto" data-checked="false" data-type="taskItem"><label><input type="checkbox"><span></span></label><div><p dir="auto">foo</p></div></li><li dir="auto" data-checked="true" data-type="taskItem"><label><input type="checkbox" checked="checked"><span></span></label><div><p dir="auto">bar</p></div></li></ul>
+    <ul dir="auto" start="1" parens="false" bullet="*" data-type="taskList"><li dir="auto" data-type="taskItem"><label><input type="checkbox"><span></span></label><div><p dir="auto">foo</p></div></li><li dir="auto" data-checked="true" data-type="taskItem"><label><input type="checkbox" checked="checked"><span></span></label><div><p dir="auto">bar</p></div></li></ul>
 09_04_00__gfm_undocumented_extensions_and_more_robust_test__task_lists__002:
   canonical: |
     <ul>
diff --git a/glfm_specification/output_example_snapshots/prosemirror_json.yml b/glfm_specification/output_example_snapshots/prosemirror_json.yml
index 95e7003a202affa32d91e17a734bf228f8b55649..084b97e6be43ce7fa6d972de4f539f92071ff601 100644
--- a/glfm_specification/output_example_snapshots/prosemirror_json.yml
+++ b/glfm_specification/output_example_snapshots/prosemirror_json.yml
@@ -20562,7 +20562,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": false
+              "checked": false,
+              "inapplicable": false
             },
             "content": [
               {
@@ -20596,7 +20597,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": true
+              "checked": true,
+              "inapplicable": false
             },
             "content": [
               {
@@ -21270,7 +21272,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": true
+              "checked": true,
+              "inapplicable": false
             },
             "content": [
               {
@@ -21292,7 +21295,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": true
+              "checked": true,
+              "inapplicable": false
             },
             "content": [
               {
@@ -21314,7 +21318,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": true
+              "checked": true,
+              "inapplicable": false
             },
             "content": [
               {
@@ -23006,7 +23011,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": true
+              "checked": true,
+              "inapplicable": false
             },
             "content": [
               {
@@ -23023,7 +23029,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": true
+              "checked": true,
+              "inapplicable": false
             },
             "content": [
               {
@@ -23040,7 +23047,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": false
+              "checked": false,
+              "inapplicable": false
             },
             "content": [
               {
@@ -23913,7 +23921,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": false
+              "checked": false,
+              "inapplicable": false
             },
             "content": [
               {
@@ -23930,7 +23939,8 @@
           {
             "type": "taskItem",
             "attrs": {
-              "checked": true
+              "checked": true,
+              "inapplicable": false
             },
             "content": [
               {
diff --git a/spec/frontend/content_editor/extensions/task_item_spec.js b/spec/frontend/content_editor/extensions/task_item_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..a38a68112cdf9efd0593f278a9afbe81f5b4a61d
--- /dev/null
+++ b/spec/frontend/content_editor/extensions/task_item_spec.js
@@ -0,0 +1,115 @@
+import TaskList from '~/content_editor/extensions/task_list';
+import TaskItem from '~/content_editor/extensions/task_item';
+import { createTestEditor, createDocBuilder } from '../test_utils';
+
+describe('content_editor/extensions/task_item', () => {
+  let tiptapEditor;
+  let doc;
+  let p;
+  let taskList;
+  let taskItem;
+
+  beforeEach(() => {
+    tiptapEditor = createTestEditor({ extensions: [TaskList, TaskItem] });
+
+    ({
+      builders: { doc, p, taskList, taskItem },
+    } = createDocBuilder({
+      tiptapEditor,
+      names: {
+        taskItem: { nodeType: TaskItem.name },
+        taskList: { nodeType: TaskList.name },
+      },
+    }));
+  });
+
+  it('renders a regular task item for non-inapplicable items', () => {
+    const initialDoc = doc(taskList(taskItem(p('foo'))));
+
+    tiptapEditor.commands.setContent(initialDoc.toJSON());
+
+    expect(tiptapEditor.view.dom.querySelector('li')).toMatchInlineSnapshot(`
+      <li
+        data-checked="false"
+        dir="auto"
+      >
+        <label>
+          <input
+            type="checkbox"
+          />
+          <span />
+        </label>
+        <div>
+          <p
+            dir="auto"
+          >
+            foo
+          </p>
+        </div>
+      </li>
+    `);
+  });
+
+  it('renders task item as disabled if it is inapplicable', () => {
+    const initialDoc = doc(taskList(taskItem({ inapplicable: true }, p('foo'))));
+
+    tiptapEditor.commands.setContent(initialDoc.toJSON());
+
+    expect(tiptapEditor.view.dom.querySelector('li')).toMatchInlineSnapshot(`
+      <li
+        data-checked="false"
+        data-inapplicable="true"
+        dir="auto"
+      >
+        <label>
+          <input
+            disabled=""
+            type="checkbox"
+          />
+          <span />
+        </label>
+        <div>
+          <p
+            dir="auto"
+          >
+            foo
+          </p>
+        </div>
+      </li>
+    `);
+  });
+
+  it('ignores any <s> tags in the task item', () => {
+    tiptapEditor.commands.setContent(`
+      <ul dir="auto" class="task-list">
+        <li class="task-list-item inapplicable">
+          <input disabled="" data-inapplicable="" class="task-list-item-checkbox" type="checkbox">
+          <s>foo</s>
+        </li>
+      </ul>
+    `);
+
+    expect(tiptapEditor.view.dom.querySelector('li')).toMatchInlineSnapshot(`
+      <li
+        data-checked="false"
+        data-inapplicable="true"
+        dir="auto"
+      >
+        <label>
+          <input
+            disabled=""
+            type="checkbox"
+          />
+          <span />
+        </label>
+        <div>
+          <p
+            dir="auto"
+          >
+            foo
+          </p>
+        </div>
+      </li>
+    `);
+  });
+});
diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js
index c329a12bcc4aff008ed0e638f57920c468ab60fc..93e10cf9f5b9d45bdaf52b61dbb4736784732d12 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -660,6 +660,24 @@ var a = 0;
     );
   });
 
+  it('correctly serializes a task list with inapplicable items', () => {
+    expect(
+      serialize(
+        taskList(
+          taskItem({ checked: true }, paragraph('list item 1')),
+          taskItem({ checked: true, inapplicable: true }, paragraph('list item 2')),
+          taskItem(paragraph('list item 3')),
+        ),
+      ),
+    ).toBe(
+      `
+* [x] list item 1
+* [~] list item 2
+* [ ] list item 3
+    `.trim(),
+    );
+  });
+
   it('correctly serializes bullet task list with different bullet styles', () => {
     expect(
       serialize(