File CVE-2024-43805.patch of Package python-jupyterlab.18615

From 42507491730b57908cfe4f048c2f84b3b92243bf Mon Sep 17 00:00:00 2001
From: nkrapp <nico.krapp@suse.com>
Date: Fri, 6 Sep 2024 19:11:27 +0200
Subject: [PATCH] fix-cve-2024-43805

---
 .../apputils-extension/schema/sanitizer.json  | 25 +++++++++++
 packages/apputils-extension/src/index.ts      | 41 +++++++++++++++++++
 packages/apputils/src/sanitizer.ts            | 37 +++++++++++------
 3 files changed, 91 insertions(+), 12 deletions(-)
 create mode 100644 packages/apputils-extension/schema/sanitizer.json

diff --git a/packages/apputils-extension/schema/sanitizer.json b/packages/apputils-extension/schema/sanitizer.json
new file mode 100644
index 0000000000..36c28a3a4e
--- /dev/null
+++ b/packages/apputils-extension/schema/sanitizer.json
@@ -0,0 +1,25 @@
+{
+  "title": "HTML Sanitizer",
+  "description": "HTML Sanitizer settings.",
+  "jupyter.lab.setting-icon": "ui-components:html5",
+  "additionalProperties": false,
+  "properties": {
+    "allowedSchemes": {
+      "title": "Allowed URL Scheme",
+      "description": "Scheme allowed by the HTML sanitizer.",
+      "type": "array",
+      "uniqueItems": true,
+      "items": {
+        "type": "string"
+      },
+      "default": ["http", "https", "ftp", "mailto", "tel"]
+    },
+    "allowNamedProperties": {
+      "type": "boolean",
+      "title": "Allow named properties",
+      "description": "Whether to allow untrusted elements to include `name` and `id` attributes. These attributes are stripped by default to prevent DOM clobbering attacks.",
+      "default": false
+    }
+  },
+  "type": "object"
+}
diff --git a/packages/apputils-extension/src/index.ts b/packages/apputils-extension/src/index.ts
index 852c4232da..4fe2e9bd0c 100644
--- a/packages/apputils-extension/src/index.ts
+++ b/packages/apputils-extension/src/index.ts
@@ -485,6 +485,47 @@ const utilityCommands: JupyterFrontEndPlugin<void> = {
   }
 };
 
+/**
+ * The default HTML sanitizer.
+ */
+const sanitizer: JupyterFrontEndPlugin<ISanitizer> = {
+  id: '@jupyter/apputils-extension:sanitizer',
+  autoStart: true,
+  provides: ISanitizer,
+  requires: [ISettingRegistry],
+  activate: (app: JupyterFrontEnd, settings: ISettingRegistry): ISanitizer => {
+    const sanitizer = new Sanitizer();
+    const loadSetting = (setting: ISettingRegistry.ISettings): void => {
+      const allowedSchemes = setting.get('allowedSchemes').composite as Array<
+        string
+      >;
+      const allowNamedProperties = setting.get('allowNamedProperties')
+        .composite as boolean;
+
+      if (allowedSchemes) {
+        sanitizer.setAllowedSchemes(allowedSchemes);
+      }
+
+      sanitizer.setAllowNamedProperties(allowNamedProperties);
+    };
+
+    // Wait for the application to be restored and
+    // for the settings for this plugin to be loaded
+    settings
+      .load('@jupyterlab/apputils-extension:sanitizer')
+      .then(setting => {
+        // Read the settings
+        loadSetting(setting);
+        // Listen for your plugin setting changes using Signal
+        setting.changed.connect(loadSetting);
+      })
+      .catch(reason => {
+        console.error(`Failed to load sanitizer settings:`, reason);
+      });
+    return sanitizer;
+  }
+};
+
 /**
  * Export the plugins as default.
  */
diff --git a/packages/apputils/src/sanitizer.ts b/packages/apputils/src/sanitizer.ts
index 7b479273c7..9f10518a1e 100644
--- a/packages/apputils/src/sanitizer.ts
+++ b/packages/apputils/src/sanitizer.ts
@@ -451,6 +451,9 @@ class CssProp {
  * A class to sanitize HTML strings.
  */
 class Sanitizer implements ISanitizer {
+  constructor() {
+    this._options = this._generateOptions();
+  }
   /**
    * Sanitize an HTML string.
    *
@@ -464,7 +467,17 @@ class Sanitizer implements ISanitizer {
     return sanitize(dirty, { ...this._options, ...(options || {}) });
   }
 
-  private _options: sanitize.IOptions = {
+  /**
+   * Set the whether to allow `name` and `id` attributes.
+   */
+  setAllowNamedProperties(allowNamedProperties: boolean): void {
+    this._allowNamedProperties = allowNamedProperties;
+    this._options = this._generateOptions();
+  }
+
+  private _allowNamedProperties: boolean = false;
+  private _options: sanitize.IOptions;
+  private _generateOptions = (): sanitize.IOptions => ({
     // HTML tags that are allowed to be used. Tags were extracted from Google Caja
     allowedTags: [
       'a',
@@ -579,7 +592,7 @@ class Sanitizer implements ISanitizer {
         'dir',
         'draggable',
         'hidden',
-        'id',
+        ...(this._allowNamedProperties ? ['id'] : []),
         'inert',
         'itemprop',
         'itemref',
@@ -596,7 +609,7 @@ class Sanitizer implements ISanitizer {
         'coords',
         'href',
         'hreflang',
-        'name',
+        ...(this._allowNamedProperties ? ['name'] : []),
         'rel',
         'shape',
         'tabindex',
@@ -625,7 +638,7 @@ class Sanitizer implements ISanitizer {
       bdo: ['dir'],
       blockquote: ['cite'],
       br: ['clear'],
-      button: ['accesskey', 'disabled', 'name', 'tabindex', 'type', 'value'],
+      button: ['accesskey', 'disabled', ...(this._allowNamedProperties ? ['name'] : []), 'tabindex', 'type', 'value'],
       canvas: ['height', 'width'],
       caption: ['align'],
       col: ['align', 'char', 'charoff', 'span', 'valign', 'width'],
@@ -652,7 +665,7 @@ class Sanitizer implements ISanitizer {
         'autocomplete',
         'enctype',
         'method',
-        'name',
+        ...(this._allowNamedProperties ? ['name'] : []),
         'novalidate'
       ],
       h1: ['align'],
@@ -677,7 +690,7 @@ class Sanitizer implements ISanitizer {
         'height',
         'hspace',
         'ismap',
-        'name',
+        ...(this._allowNamedProperties ? ['name'] : []),
         'src',
         'usemap',
         'vspace',
@@ -698,7 +711,7 @@ class Sanitizer implements ISanitizer {
         'maxlength',
         'min',
         'multiple',
-        'name',
+        ...(this._allowNamedProperties ? ['name'] : []),
         'placeholder',
         'readonly',
         'required',
@@ -714,13 +727,13 @@ class Sanitizer implements ISanitizer {
       label: ['accesskey', 'for'],
       legend: ['accesskey', 'align'],
       li: ['type', 'value'],
-      map: ['name'],
+      map: this._allowNamedProperties ? ['name'] : [],
       menu: ['compact', 'label', 'type'],
       meter: ['high', 'low', 'max', 'min', 'value'],
       ol: ['compact', 'reversed', 'start', 'type'],
       optgroup: ['disabled', 'label'],
       option: ['disabled', 'label', 'selected', 'value'],
-      output: ['for', 'name'],
+      output: ['for', ...(this._allowNamedProperties ? ['name'] : [])],
       p: ['align'],
       pre: ['width'],
       progress: ['max', 'min', 'value'],
@@ -729,7 +742,7 @@ class Sanitizer implements ISanitizer {
         'autocomplete',
         'disabled',
         'multiple',
-        'name',
+        ...(this._allowNamedProperties ? ['name'] : []),
         'required',
         'size',
         'tabindex'
@@ -769,7 +782,7 @@ class Sanitizer implements ISanitizer {
         'cols',
         'disabled',
         'inputmode',
-        'name',
+        ...(this._allowNamedProperties ? ['name'] : []),
         'placeholder',
         'readonly',
         'required',
@@ -961,7 +974,7 @@ class Sanitizer implements ISanitizer {
     // Since embedded data is no longer deemed to be a threat, validation can be skipped.
     // See https://github.com/jupyterlab/jupyterlab/issues/5183
     allowedSchemesAppliedToAttributes: ['href', 'cite']
-  };
+  });
 }
 
 /**
-- 
2.46.0

openSUSE Build Service is sponsored by