CVE-2022-2134 (published 2022-06-20T15:15Z)

Allocation of Resources Without Limits or Throttling in GitHub repository inventree/inventree prior to 0.8.0.

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-770
cwe_name: Allocation of Resources Without Limits or Throttling
description: The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
extended_description: Code frequently has to work with limited resources, so programmers must be careful to ensure that resources are not consumed too quickly, or too easily.  Without use of quotas, resource limits, or other protection mechanisms, it can be easy for an attacker to consume many resources by rapidly making many requests, or causing larger resources to be used than is needed. When too many resources are allocated, or if a single resource is too large, then it can prevent the code from working correctly, possibly leading to a denial of service.
         

Fix information:
repo_url: https://github.com/inventree/inventree
commit_details: repo_url: https://github.com/inventree/inventree
author: Oliver
author_date: 2022-06-20 22:20:04+10:00
msg: Remove reliance on django-markdownx (#3231)

* Remove reliance on django-markdownx

- We are now rendering notes on the client side using easymde
- No longer any need to utilize the markdownx integration
- Adds character limit for notes fields`

* Adjust legacy migrations - remove references to markdownx

* Fix bug for company notes field
repository: repo_url: https://github.com/inventree/inventree
repo_name: inventree/InvenTree
description: Open Source Inventory Management System
repo_language: Python
owner: inventree
file_changes: filename: fields.py
change_type: ModificationType.MODIFY
diff: @@ -157,3 +157,19 @@ class RoundingDecimalField(models.DecimalField):
         defaults.update(kwargs)
 
         return super().formfield(**kwargs)
+
+
+class InvenTreeNotesField(models.TextField):
+    """Custom implementation of a 'notes' field"""
+
+    # Maximum character limit for the various 'notes' fields
+    NOTES_MAX_LENGTH = 50000
+
+    def __init__(self, **kwargs):
+        """Configure default initial values for this field"""
+        kwargs['max_length'] = self.NOTES_MAX_LENGTH
+        kwargs['verbose_name'] = _('Notes')
+        kwargs['blank'] = True
+        kwargs['null'] = True
+
+        super().__init__(**kwargs)

programming_language: Python
filename: settings.py
change_type: ModificationType.MODIFY
diff: @@ -15,7 +15,6 @@ import random
 import socket
 import string
 import sys
-from datetime import datetime
 
 import django.conf.locale
 from django.core.files.storage import default_storage
@@ -253,7 +252,6 @@ INSTALLED_APPS = [
     'import_export',                        # Import / export tables to file
     'django_cleanup.apps.CleanupConfig',    # Automatically delete orphaned MEDIA files
     'mptt',                                 # Modified Preorder Tree Traversal
-    'markdownx',                            # Markdown editing
     'markdownify',                          # Markdown template rendering
     'django_admin_shell',                   # Python shell for the admin interface
     'djmoney',                              # django-money integration
@@ -875,10 +873,6 @@ ACCOUNT_ADAPTER = 'InvenTree.forms.CustomAccountAdapter'
 REMOTE_LOGIN = get_setting('INVENTREE_REMOTE_LOGIN', CONFIG.get('remote_login', False))
 REMOTE_LOGIN_HEADER = get_setting('INVENTREE_REMOTE_LOGIN_HEADER', CONFIG.get('remote_login_header', 'REMOTE_USER'))
 
-# Markdownx configuration
-# Ref: https://neutronx.github.io/django-markdownx/customization/
-MARKDOWNX_MEDIA_PATH = datetime.now().strftime('markdownx/%Y/%m/%d')
-
 # Markdownify configuration
 # Ref: https://django-markdownify.readthedocs.io/en/latest/settings.html
 

programming_language: Python
filename: dark-reader.css
change_type: ModificationType.MODIFY
diff: @@ -3539,15 +3539,6 @@ a.ui-button:active,
 .index-action-selected {
     background-color: rgb(32, 34, 36);
 }
-.markdownx .row {
-    border-color: rgb(31, 31, 92);
-}
-.markdownx-editor {
-    border-color: rgb(31, 31, 92);
-}
-.markdownx-preview {
-    border-color: rgb(31, 31, 92);
-}
 .progress {
     background-image: initial;
     background-color: rgb(32, 34, 36);

programming_language: CSS
filename: inventree.css
change_type: ModificationType.MODIFY
diff: @@ -63,30 +63,10 @@ main {
     background-color: #EEEEF5;
 }
 
-.markdownx .row {
-    margin: 5px;
-    padding: 5px;
-    border: 1px solid #cce;
-    border-radius: 4px;
-}
-
-.markdownx-editor {
-    width: 100%;
-    border: 1px solid #cce;
-    border-radius: 3px;
-    padding: 10px;
-}
-
 .panel-content {
     padding: 10px;
 }
 
-.markdownx-preview {
-    border: 1px solid #cce;
-    border-radius: 3px;
-    padding: 10px;
-}
-
 /* Progress bars */
 
 .progress {

programming_language: CSS
filename: urls.py
change_type: ModificationType.MODIFY
diff: @@ -126,9 +126,6 @@ backendpatterns = [
 
     re_path(r'^api/', include(apipatterns)),
     re_path(r'^api-doc/', include_docs_urls(title='InvenTree API')),
-
-    # 3rd party endpoints
-    re_path(r'^markdownx/', include('markdownx.urls')),
 ]
 
 frontendpatterns = [

programming_language: Python
filename: 0008_auto_20200201_1247.py
change_type: ModificationType.MODIFY
diff: @@ -1,7 +1,6 @@
 # Generated by Django 2.2.9 on 2020-02-01 12:47
 
-from django.db import migrations
-import markdownx.models
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -14,6 +13,6 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='build',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Extra build notes'),
+            field=models.TextField(blank=True, help_text='Extra build notes'),
         ),
     ]

programming_language: Python
filename: 0014_auto_20200425_1243.py
change_type: ModificationType.MODIFY
diff: @@ -4,7 +4,6 @@ import InvenTree.fields
 import django.core.validators
 from django.db import migrations, models
 import django.db.models.deletion
-import markdownx.models
 import mptt.fields
 
 
@@ -31,7 +30,7 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='build',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Extra build notes', verbose_name='Notes'),
+            field=models.TextField(blank=True, help_text='Extra build notes', verbose_name='Notes'),
         ),
         migrations.AlterField(
             model_name='build',

programming_language: Python
filename: 0035_alter_build_notes.py
change_type: ModificationType.ADD
diff: @@ -0,0 +1,19 @@
+# Generated by Django 3.2.13 on 2022-06-20 07:28
+
+import InvenTree.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('build', '0034_alter_build_reference_int'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='build',
+            name='notes',
+            field=InvenTree.fields.InvenTreeNotesField(blank=True, help_text='Extra build notes', max_length=50000, null=True, verbose_name='Notes'),
+        ),
+    ]

programming_language: Python
filename: models.py
change_type: ModificationType.MODIFY
diff: @@ -16,8 +16,6 @@ from django.dispatch.dispatcher import receiver
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from markdownx.models import MarkdownxField
-
 from mptt.models import MPTTModel, TreeForeignKey
 from mptt.exceptions import InvalidMove
 
@@ -320,9 +318,8 @@ class Build(MPTTModel, ReferenceIndexingMixin):
         blank=True, help_text=_('Link to external URL')
     )
 
-    notes = MarkdownxField(
-        verbose_name=_('Notes'),
-        blank=True, help_text=_('Extra build notes')
+    notes = InvenTree.fields.InvenTreeNotesField(
+        help_text=_('Extra build notes')
     )
 
     def sub_builds(self, cascade=True):

programming_language: Python
filename: 0010_auto_20200201_1231.py
change_type: ModificationType.MODIFY
diff: @@ -1,7 +1,6 @@
 # Generated by Django 2.2.9 on 2020-02-01 12:31
 
-from django.db import migrations
-import markdownx.models
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -14,6 +13,6 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='company',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True),
+            field=models.TextField(blank=True),
         ),
     ]

programming_language: Python
filename: 0032_auto_20210403_1837.py
change_type: ModificationType.MODIFY
diff: @@ -5,7 +5,6 @@ import company.models
 import django.core.validators
 from django.db import migrations, models
 import django.db.models.deletion
-import markdownx.models
 import stdimage.models
 
 
@@ -44,7 +43,7 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='company',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, verbose_name='Notes'),
+            field=models.TextField(blank=True, verbose_name='Notes'),
         ),
         migrations.AlterField(
             model_name='supplierpart',

programming_language: Python
filename: 0045_alter_company_notes.py
change_type: ModificationType.ADD
diff: @@ -0,0 +1,19 @@
+# Generated by Django 3.2.13 on 2022-06-20 11:23
+
+import InvenTree.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('company', '0044_auto_20220607_2204'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='company',
+            name='notes',
+            field=InvenTree.fields.InvenTreeNotesField(blank=True, help_text='Company Notes', max_length=50000, null=True, verbose_name='Notes'),
+        ),
+    ]

programming_language: Python
filename: models.py
change_type: ModificationType.MODIFY
diff: @@ -11,12 +11,12 @@ from django.db.models import Q, Sum, UniqueConstraint
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from markdownx.models import MarkdownxField
 from moneyed import CURRENCIES
 from stdimage.models import StdImageField
 
 import common.models
 import common.settings
+import InvenTree.fields
 import InvenTree.validators
 from common.settings import currency_code_default
 from InvenTree.fields import InvenTreeURLField
@@ -135,7 +135,7 @@ class Company(models.Model):
         verbose_name=_('Image'),
     )
 
-    notes = MarkdownxField(blank=True, verbose_name=_('Notes'))
+    notes = InvenTree.fields.InvenTreeNotesField(help_text=_("Company Notes"))
 
     is_customer = models.BooleanField(default=False, verbose_name=_('is customer'), help_text=_('Do you sell items to this company?'))
 

programming_language: Python
filename: 0015_auto_20200201_2346.py
change_type: ModificationType.MODIFY
diff: @@ -1,7 +1,6 @@
 # Generated by Django 2.2.9 on 2020-02-01 23:46
 
-from django.db import migrations
-import markdownx.models
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -14,6 +13,6 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='purchaseorder',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Order notes'),
+            field=models.TextField(blank=True, help_text='Order notes'),
         ),
     ]

programming_language: Python
filename: 0020_auto_20200420_0940.py
change_type: ModificationType.MODIFY
diff: @@ -6,7 +6,6 @@ from django.conf import settings
 import django.core.validators
 from django.db import migrations, models
 import django.db.models.deletion
-import markdownx.models
 
 
 class Migration(migrations.Migration):
@@ -29,7 +28,7 @@ class Migration(migrations.Migration):
                 ('status', models.PositiveIntegerField(choices=[(10, 'Pending'), (20, 'Placed'), (30, 'Complete'), (40, 'Cancelled'), (50, 'Lost'), (60, 'Returned')], default=10, help_text='Order status')),
                 ('issue_date', models.DateField(blank=True, null=True)),
                 ('complete_date', models.DateField(blank=True, null=True)),
-                ('notes', markdownx.models.MarkdownxField(blank=True, help_text='Order notes')),
+                ('notes', models.TextField(blank=True, help_text='Order notes')),
                 ('customer_reference', models.CharField(blank=True, help_text='Customer order reference code', max_length=64)),
                 ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
                 ('customer', models.ForeignKey(help_text='Customer', limit_choices_to={True, 'is_supplier'}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sales_orders', to='company.Company')),

programming_language: Python
filename: 0044_auto_20210404_2016.py
change_type: ModificationType.MODIFY
diff: @@ -6,7 +6,6 @@ from django.conf import settings
 import django.core.validators
 from django.db import migrations, models
 import django.db.models.deletion
-import markdownx.models
 
 
 class Migration(migrations.Migration):
@@ -43,7 +42,7 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='purchaseorder',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Order notes', verbose_name='Notes'),
+            field=models.TextField(blank=True, help_text='Order notes', verbose_name='Notes'),
         ),
         migrations.AlterField(
             model_name='purchaseorder',
@@ -148,7 +147,7 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='salesorder',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Order notes', verbose_name='Notes'),
+            field=models.TextField(blank=True, help_text='Order notes', verbose_name='Notes'),
         ),
         migrations.AlterField(
             model_name='salesorder',

programming_language: Python
filename: 0053_salesordershipment.py
change_type: ModificationType.MODIFY
diff: @@ -4,10 +4,6 @@ from django.conf import settings
 from django.db import migrations, models
 import django.db.models.deletion
 
-import order.models
-
-import markdownx.models
-
 
 class Migration(migrations.Migration):
 
@@ -23,7 +19,7 @@ class Migration(migrations.Migration):
                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('shipment_date', models.DateField(blank=True, help_text='Date of shipment', null=True, verbose_name='Shipment Date')),
                 ('reference', models.CharField(default='1', help_text='Shipment reference', max_length=100, verbose_name='Reference')),
-                ('notes', markdownx.models.MarkdownxField(blank=True, help_text='Shipment notes', verbose_name='Notes')),
+                ('notes', models.TextField(blank=True, help_text='Shipment notes', verbose_name='Notes')),
                 ('checked_by', models.ForeignKey(blank=True, help_text='User who checked this shipment', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Checked By')),
                 ('order', models.ForeignKey(help_text='Sales Order', on_delete=django.db.models.deletion.CASCADE, related_name='shipments', to='order.salesorder', verbose_name='Order')),
             ],

programming_language: Python
filename: 0070_auto_20220620_0728.py
change_type: ModificationType.ADD
diff: @@ -0,0 +1,29 @@
+# Generated by Django 3.2.13 on 2022-06-20 07:28
+
+import InvenTree.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('order', '0069_auto_20220524_0508'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='purchaseorder',
+            name='notes',
+            field=InvenTree.fields.InvenTreeNotesField(blank=True, help_text='Order notes', max_length=50000, null=True, verbose_name='Notes'),
+        ),
+        migrations.AlterField(
+            model_name='salesorder',
+            name='notes',
+            field=InvenTree.fields.InvenTreeNotesField(blank=True, help_text='Order notes', max_length=50000, null=True, verbose_name='Notes'),
+        ),
+        migrations.AlterField(
+            model_name='salesordershipment',
+            name='notes',
+            field=InvenTree.fields.InvenTreeNotesField(blank=True, help_text='Shipment notes', max_length=50000, null=True, verbose_name='Notes'),
+        ),
+    ]

programming_language: Python
filename: models.py
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@ from django.utils.translation import gettext_lazy as _
 from djmoney.contrib.exchange.exceptions import MissingRate
 from djmoney.contrib.exchange.models import convert_money
 from djmoney.money import Money
-from markdownx.models import MarkdownxField
 from mptt.models import TreeForeignKey
 
 import InvenTree.helpers
@@ -28,7 +27,8 @@ import InvenTree.ready
 from common.settings import currency_code_default
 from company.models import Company, SupplierPart
 from InvenTree.exceptions import log_error
-from InvenTree.fields import InvenTreeModelMoneyField, RoundingDecimalField
+from InvenTree.fields import (InvenTreeModelMoneyField, InvenTreeNotesField,
+                              RoundingDecimalField)
 from InvenTree.helpers import (decimal2string, getSetting, increment,
                                notify_responsible)
 from InvenTree.models import InvenTreeAttachment, ReferenceIndexingMixin
@@ -152,7 +152,7 @@ class Order(MetadataMixin, ReferenceIndexingMixin):
         related_name='+',
     )
 
-    notes = MarkdownxField(blank=True, verbose_name=_('Notes'), help_text=_('Order notes'))
+    notes = InvenTreeNotesField(help_text=_('Order notes'))
 
     def get_total_price(self, target_currency=None):
         """Calculates the total price of all order lines, and converts to the specified target currency.
@@ -1210,11 +1210,7 @@ class SalesOrderShipment(models.Model):
         default='1',
     )
 
-    notes = MarkdownxField(
-        blank=True,
-        verbose_name=_('Notes'),
-        help_text=_('Shipment notes'),
-    )
+    notes = InvenTreeNotesField(help_text=_('Shipment notes'))
 
     tracking_number = models.CharField(
         max_length=100,

programming_language: Python
filename: 0026_auto_20200131_1022.py
change_type: ModificationType.MODIFY
diff: @@ -1,7 +1,6 @@
 # Generated by Django 2.2.9 on 2020-01-31 10:22
 
-from django.db import migrations
-import markdownx.models
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -14,6 +13,6 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='part',
             name='notes',
-            field=markdownx.models.MarkdownxField(help_text='Part notes - supports Markdown formatting'),
+            field=models.TextField(help_text='Part notes - supports Markdown formatting'),
         ),
     ]

programming_language: Python
filename: 0029_auto_20200223_0901.py
change_type: ModificationType.MODIFY
diff: @@ -1,7 +1,6 @@
 # Generated by Django 2.2.9 on 2020-02-23 09:01
 
-from django.db import migrations
-import markdownx.models
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -14,6 +13,6 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='part',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Part notes - supports Markdown formatting'),
+            field=models.TextField(blank=True, help_text='Part notes - supports Markdown formatting'),
         ),
     ]

programming_language: Python
filename: 0048_auto_20200902_1404.py
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,6 @@
 import InvenTree.fields
 import InvenTree.validators
 
-import markdownx
-
 from django.db import migrations, models
 
 
@@ -38,7 +36,7 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='part',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Part notes - supports Markdown formatting', null=True),
+            field=models.TextField(blank=True, help_text='Part notes - supports Markdown formatting', null=True),
         ),
         migrations.AlterField(
             model_name='part',

programming_language: Python
filename: 0061_auto_20210103_2313.py
change_type: ModificationType.MODIFY
diff: @@ -4,7 +4,6 @@ import InvenTree.fields
 import InvenTree.validators
 from django.db import migrations, models
 import django.db.models.deletion
-import markdownx.models
 import mptt.fields
 import part.settings
 
@@ -65,7 +64,7 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='part',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Part notes - supports Markdown formatting', null=True, verbose_name='Notes'),
+            field=models.TextField(blank=True, help_text='Part notes - supports Markdown formatting', null=True, verbose_name='Notes'),
         ),
         migrations.AlterField(
             model_name='part',

programming_language: Python
filename: 0079_alter_part_notes.py
change_type: ModificationType.ADD
diff: @@ -0,0 +1,19 @@
+# Generated by Django 3.2.13 on 2022-06-20 07:28
+
+import InvenTree.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('part', '0078_auto_20220606_0024'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='part',
+            name='notes',
+            field=InvenTree.fields.InvenTreeNotesField(blank=True, help_text='Part notes', max_length=50000, null=True, verbose_name='Notes'),
+        ),
+    ]

programming_language: Python
filename: models.py
change_type: ModificationType.MODIFY
diff: @@ -25,7 +25,6 @@ from django_cleanup import cleanup
 from djmoney.contrib.exchange.exceptions import MissingRate
 from djmoney.contrib.exchange.models import convert_money
 from jinja2 import Template
-from markdownx.models import MarkdownxField
 from mptt.exceptions import InvalidMove
 from mptt.managers import TreeManager
 from mptt.models import MPTTModel, TreeForeignKey
@@ -41,7 +40,7 @@ from common.models import InvenTreeSetting
 from common.settings import currency_code_default
 from company.models import SupplierPart
 from InvenTree import helpers, validators
-from InvenTree.fields import InvenTreeURLField
+from InvenTree.fields import InvenTreeNotesField, InvenTreeURLField
 from InvenTree.helpers import decimal2money, decimal2string, normalize
 from InvenTree.models import (DataImportMixin, InvenTreeAttachment,
                               InvenTreeTree)
@@ -920,11 +919,7 @@ class Part(MetadataMixin, MPTTModel):
         verbose_name=_('Virtual'),
         help_text=_('Is this a virtual part, such as a software product or license?'))
 
-    notes = MarkdownxField(
-        blank=True, null=True,
-        verbose_name=_('Notes'),
-        help_text=_('Part notes - supports Markdown formatting')
-    )
+    notes = InvenTreeNotesField(help_text=_('Part notes'))
 
     bom_checksum = models.CharField(max_length=128, blank=True, verbose_name=_('BOM checksum'), help_text=_('Stored BOM checksum'))
 

programming_language: Python
filename: test_api.py
change_type: ModificationType.MODIFY
diff: @@ -1305,6 +1305,22 @@ class PartDetailTests(InvenTreeAPITestCase):
         self.assertFalse('hello' in part.metadata)
         self.assertEqual(part.metadata['x'], 'y')
 
+    def test_part_notes(self):
+        """Unit tests for the part 'notes' field"""
+
+        # Ensure that we cannot upload a very long piece of text
+        url = reverse('api-part-detail', kwargs={'pk': 1})
+
+        response = self.patch(
+            url,
+            {
+                'notes': 'abcde' * 10001
+            },
+            expected_code=400
+        )
+
+        self.assertIn('Ensure this field has no more than 50000 characters', str(response.data['notes']))
+
 
 class PartAPIAggregationTest(InvenTreeAPITestCase):
     """Tests to ensure that the various aggregation annotations are working correctly..."""

programming_language: Python
filename: 0018_auto_20200202_0103.py
change_type: ModificationType.MODIFY
diff: @@ -1,7 +1,6 @@
 # Generated by Django 2.2.9 on 2020-02-02 01:03
 
-from django.db import migrations
-import markdownx.models
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -14,6 +13,6 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='stockitem',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Stock Item Notes'),
+            field=models.TextField(blank=True, help_text='Stock Item Notes'),
         ),
     ]

programming_language: Python
filename: 0020_auto_20200206_1213.py
change_type: ModificationType.MODIFY
diff: @@ -1,7 +1,6 @@
 # Generated by Django 2.2.9 on 2020-02-06 12:13
 
-from django.db import migrations
-import markdownx.models
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
@@ -14,6 +13,6 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='stockitem',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Stock Item Notes', null=True),
+            field=models.TextField(blank=True, help_text='Stock Item Notes', null=True),
         ),
     ]

programming_language: Python
filename: 0034_auto_20200426_0602.py
change_type: ModificationType.MODIFY
diff: @@ -4,7 +4,6 @@ import InvenTree.fields
 import django.core.validators
 from django.db import migrations, models
 import django.db.models.deletion
-import markdownx.models
 import mptt.fields
 
 
@@ -56,7 +55,7 @@ class Migration(migrations.Migration):
         migrations.AlterField(
             model_name='stockitem',
             name='notes',
-            field=markdownx.models.MarkdownxField(blank=True, help_text='Stock Item Notes', null=True, verbose_name='Notes'),
+            field=models.TextField(blank=True, help_text='Stock Item Notes', null=True, verbose_name='Notes'),
         ),
         migrations.AlterField(
             model_name='stockitem',

programming_language: Python
filename: 0077_alter_stockitem_notes.py
change_type: ModificationType.ADD
diff: @@ -0,0 +1,19 @@
+# Generated by Django 3.2.13 on 2022-06-20 07:28
+
+import InvenTree.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('stock', '0076_alter_stockitem_status'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='stockitem',
+            name='notes',
+            field=InvenTree.fields.InvenTreeNotesField(blank=True, help_text='Stock Item Notes', max_length=50000, null=True, verbose_name='Notes'),
+        ),
+    ]

programming_language: Python
filename: models.py
change_type: ModificationType.MODIFY
diff: @@ -18,7 +18,6 @@ from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
 from jinja2 import Template
-from markdownx.models import MarkdownxField
 from mptt.managers import TreeManager
 from mptt.models import MPTTModel, TreeForeignKey
 
@@ -29,7 +28,8 @@ import InvenTree.tasks
 import label.models
 import report.models
 from company import models as CompanyModels
-from InvenTree.fields import InvenTreeModelMoneyField, InvenTreeURLField
+from InvenTree.fields import (InvenTreeModelMoneyField, InvenTreeNotesField,
+                              InvenTreeURLField)
 from InvenTree.models import InvenTreeAttachment, InvenTreeTree
 from InvenTree.serializers import extract_int
 from InvenTree.status_codes import StockHistoryCode, StockStatus
@@ -708,11 +708,7 @@ class StockItem(MetadataMixin, MPTTModel):
         choices=StockStatus.items(),
         validators=[MinValueValidator(0)])
 
-    notes = MarkdownxField(
-        blank=True, null=True,
-        verbose_name=_("Notes"),
-        help_text=_('Stock Item Notes')
-    )
+    notes = InvenTreeNotesField(help_text=_('Stock Item Notes'))
 
     purchase_price = InvenTreeModelMoneyField(
         max_digits=19,

programming_language: Python
filename: requirements.txt
change_type: ModificationType.MODIFY
diff: @@ -19,7 +19,6 @@ django-formtools==2.3                   # Form wizard tools
 django-import-export==2.5.0             # Data import / export for admin interface
 django-maintenance-mode==0.16.1         # Shut down application while reloading etc.
 django-markdownify==0.8.0               # Markdown rendering
-django-markdownx==3.0.1                 # Markdown form fields
 django-money==1.1                       # Django app for currency management
 django-mptt==0.11.0                     # Modified Preorder Tree Traversal
 django-redis>=5.0.0                     # Redis integration

programming_language: Python