Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-nbconvert for openSUSE:Factory checked in at 2022-08-11 18:33:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-nbconvert (Old) and /work/SRC/openSUSE:Factory/.python-nbconvert.new.1521 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-nbconvert" Thu Aug 11 18:33:01 2022 rev:14 rq:994560 version:6.5.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-nbconvert/python-nbconvert.changes 2022-06-05 21:28:39.665056916 +0200 +++ /work/SRC/openSUSE:Factory/.python-nbconvert.new.1521/python-nbconvert.changes 2022-08-11 18:33:17.638200044 +0200 @@ -1,0 +2,35 @@ +Thu Aug 11 14:01:34 UTC 2022 - Arun Persaud <a...@gmx.de> + +- specfile + * remove skip python 2, since we require python >= 3.7 anyway + * updates patches + * require lxml + +- update to version 6.5.3: + * Fix title (#1833) + +- changes from version 6.5.2: + * escape_html: prevent escaping quotes on widgets JSON reprs (#1829) + * Fix linters (#1828) + * pre-commit-ci[bot] authored and SylvainCorlay committed 2 days ago + * Remove downloaded CSS from repository + +- changes from version 6.5.1: + * Fix pre-commit + * Fix tests + * Run black and prettier + * Run test on 6.x branch + * Convert input to string prior to escape HTML + * Check input type before escaping + * GHSL-2021-1017, GHSL-2021-1020, GHSL-2021-1021 + * GHSL-2021-1026, GHSL-2021-1025 + * GHSL-2021-1024 + * GHSL-2021-1023 + * GHSL-2021-1022 + * GHSL-2021-1019 + * GHSL-2021-1018 + * GHSL-2021-1027, GHSL-2021-1028 + * GHSL-2021-1014, GHSL-2021-1015, GHSL-2021-1016 + * GHSL-2021-1013 + +------------------------------------------------------------------- Old: ---- nbconvert-6.5.0.tar.gz New: ---- nbconvert-6.5.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-nbconvert.spec ++++++ --- /var/tmp/diff_new_pack.3Q8kk1/_old 2022-08-11 18:33:18.230199135 +0200 +++ /var/tmp/diff_new_pack.3Q8kk1/_new 2022-08-11 18:33:18.234199130 +0200 @@ -30,9 +30,8 @@ %bcond_with libalternatives %endif %{?!python_module:%define python_module() python3-%{**}} -%define skip_python2 1 Name: python-nbconvert%{psuffix} -Version: 6.5.0 +Version: 6.5.3 Release: 0 Summary: Conversion of Jupyter Notebooks License: BSD-3-Clause @@ -46,6 +45,7 @@ Patch2: ignore-bleach-deprecation-test.patch BuildRequires: %{python_module base >= 3.7} BuildRequires: %{python_module beautifulsoup4} +BuildRequires: %{python_module lxml} BuildRequires: %{python_module packaging} BuildRequires: %{python_module setuptools} BuildRequires: fdupes @@ -61,6 +61,7 @@ Requires: python-entrypoints >= 0.2.2 Requires: python-jupyter-core >= 4.7 Requires: python-jupyterlab-pygments +Requires: python-lxml Requires: python-nbclient >= 0.5 Requires: python-nbformat >= 5.1 Requires: python-packaging ++++++ ignore-bleach-deprecation-test.patch ++++++ --- /var/tmp/diff_new_pack.3Q8kk1/_old 2022-08-11 18:33:18.274199068 +0200 +++ /var/tmp/diff_new_pack.3Q8kk1/_new 2022-08-11 18:33:18.278199062 +0200 @@ -1,12 +1,11 @@ -Index: nbconvert-6.5.0/pyproject.toml +Index: nbconvert-6.5.3/pyproject.toml =================================================================== ---- nbconvert-6.5.0.orig/pyproject.toml -+++ nbconvert-6.5.0/pyproject.toml -@@ -21,5 +21,5 @@ filterwarnings = [ +--- nbconvert-6.5.3.orig/pyproject.toml ++++ nbconvert-6.5.3/pyproject.toml +@@ -21,4 +21,5 @@ filterwarnings = [ "ignore:unclosed <socket.socket:ResourceWarning", "ignore:unclosed event loop:ResourceWarning", "ignore:There is no current event loop:DeprecationWarning", -- + "ignore:Support for bleach <5 will be removed in a future version of nbconvert:DeprecationWarning", ] ++++++ nbconvert-6.5.0.tar.gz -> nbconvert-6.5.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/PKG-INFO new/nbconvert-6.5.3/PKG-INFO --- old/nbconvert-6.5.0/PKG-INFO 2022-04-11 11:09:33.618694000 +0200 +++ new/nbconvert-6.5.3/PKG-INFO 2022-08-11 13:52:08.571465300 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: nbconvert -Version: 6.5.0 +Version: 6.5.3 Summary: Converting Jupyter Notebooks Home-page: https://jupyter.org Author: Jupyter Development Team @@ -122,5 +122,3 @@ - [Project Jupyter website](https://jupyter.org) [jinja]: http://jinja.pocoo.org/ - - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/nbconvert/_version.py new/nbconvert-6.5.3/nbconvert/_version.py --- old/nbconvert-6.5.0/nbconvert/_version.py 2022-04-11 11:08:24.340618100 +0200 +++ new/nbconvert-6.5.3/nbconvert/_version.py 2022-08-11 13:49:49.310203300 +0200 @@ -1,4 +1,4 @@ -version_info = (6, 5, 0) +version_info = (6, 5, 3) pre_info = "" dev_info = "" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/nbconvert/exporters/html.py new/nbconvert-6.5.3/nbconvert/exporters/html.py --- old/nbconvert-6.5.0/nbconvert/exporters/html.py 2022-04-11 11:07:42.625555800 +0200 +++ new/nbconvert-6.5.3/nbconvert/exporters/html.py 2022-08-09 16:16:56.749613000 +0200 @@ -149,6 +149,14 @@ help="Template specific theme(e.g. the name of a JupyterLab CSS theme distributed as prebuilt extension for the lab template)", ).tag(config=True) + sanitize_html = Bool( + False, + help=( + "Whether the HTML in Markdown cells and cell outputs should be sanitized." + "This should be set to True by nbviewer or similar tools." + ), + ).tag(config=True) + embed_images = Bool( False, help="Whether or not to embed images as base64 in markdown cells." ).tag(config=True) @@ -287,4 +295,5 @@ resources["jupyter_widgets_base_url"] = self.jupyter_widgets_base_url resources["widget_renderer_url"] = self.widget_renderer_url resources["html_manager_semver_range"] = self.html_manager_semver_range + resources["should_sanitize_html"] = self.sanitize_html return resources diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/nbconvert/exporters/templateexporter.py new/nbconvert-6.5.3/nbconvert/exporters/templateexporter.py --- old/nbconvert-6.5.0/nbconvert/exporters/templateexporter.py 2022-04-11 11:07:42.626543000 +0200 +++ new/nbconvert-6.5.3/nbconvert/exporters/templateexporter.py 2022-08-11 10:02:47.701777200 +0200 @@ -6,6 +6,7 @@ # Distributed under the terms of the Modified BSD License. +import html import json import os import uuid @@ -21,6 +22,7 @@ TemplateNotFound, ) from jupyter_core.paths import jupyter_path +from lxml.html.clean import clean_html from traitlets import Bool, Dict, HasTraits, List, Unicode, default, observe, validate from traitlets.config import Config from traitlets.utils.importstring import import_item @@ -68,9 +70,11 @@ "get_metadata": filters.get_metadata, "convert_pandoc": filters.convert_pandoc, "json_dumps": json.dumps, - # browsers will parse </script>, closing a script tag early - # Since JSON allows escaping forward slash, this will still be parsed by JSON - "escape_html_script": lambda x: x.replace("</script>", "<\\/script>"), + # For removing any HTML + "escape_html": lambda s: html.escape(str(s)), + "escape_html_keep_quotes": lambda s: html.escape(str(s), quote=False), + # For sanitizing HTML for any XSS + "clean_html": clean_html, "strip_trailing_newline": filters.strip_trailing_newline, "text_base64": filters.text_base64, } @@ -254,7 +258,8 @@ template_extension = Unicode().tag(config=True, affects_environment=True) template_data_paths = List( - jupyter_path("nbconvert", "templates"), help="Path where templates can be installed too." + jupyter_path("nbconvert", "templates"), + help="Path where templates can be installed too.", ).tag(affects_environment=True) # Extension that the template files use. @@ -268,11 +273,13 @@ return self.file_extension exclude_input = Bool( - False, help="This allows you to exclude code cell inputs from all templates if set to True." + False, + help="This allows you to exclude code cell inputs from all templates if set to True.", ).tag(config=True) exclude_input_prompt = Bool( - False, help="This allows you to exclude input prompts from all templates if set to True." + False, + help="This allows you to exclude input prompts from all templates if set to True.", ).tag(config=True) exclude_output = Bool( @@ -281,7 +288,8 @@ ).tag(config=True) exclude_output_prompt = Bool( - False, help="This allows you to exclude output prompts from all templates if set to True." + False, + help="This allows you to exclude output prompts from all templates if set to True.", ).tag(config=True) exclude_output_stdin = Bool( @@ -290,19 +298,23 @@ ).tag(config=True) exclude_code_cell = Bool( - False, help="This allows you to exclude code cells from all templates if set to True." + False, + help="This allows you to exclude code cells from all templates if set to True.", ).tag(config=True) exclude_markdown = Bool( - False, help="This allows you to exclude markdown cells from all templates if set to True." + False, + help="This allows you to exclude markdown cells from all templates if set to True.", ).tag(config=True) exclude_raw = Bool( - False, help="This allows you to exclude raw cells from all templates if set to True." + False, + help="This allows you to exclude raw cells from all templates if set to True.", ).tag(config=True) exclude_unknown = Bool( - False, help="This allows you to exclude unknown cells from all templates if set to True." + False, + help="This allows you to exclude unknown cells from all templates if set to True.", ).tag(config=True) extra_loaders = List( @@ -341,7 +353,8 @@ super().__init__(config=config, **kw) self.observe( - self._invalidate_environment_cache, list(self.traits(affects_environment=True)) + self._invalidate_environment_cache, + list(self.traits(affects_environment=True)), ) self.observe(self._invalidate_template_cache, list(self.traits(affects_template=True))) @@ -603,7 +616,11 @@ for root_dir in root_dirs: compatibility_file = base_template + ".tpl" compatibility_path = os.path.join( - root_dir, "nbconvert", "templates", "compatibility", compatibility_file + root_dir, + "nbconvert", + "templates", + "compatibility", + compatibility_file, ) if os.path.exists(compatibility_path): found_at_least_one = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/nbconvert/exporters/tests/files/notebook_inject.ipynb new/nbconvert-6.5.3/nbconvert/exporters/tests/files/notebook_inject.ipynb --- old/nbconvert-6.5.0/nbconvert/exporters/tests/files/notebook_inject.ipynb 1970-01-01 01:00:00.000000000 +0100 +++ new/nbconvert-6.5.3/nbconvert/exporters/tests/files/notebook_inject.ipynb 2022-08-09 14:44:17.467249400 +0200 @@ -0,0 +1,303 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "79aede83-fba6-4715-bce6-9f3926b128a2", + "metadata": { + "tags": ["FOO\"><script>alert('cell_tag')</script><div \""] + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "raw", + "id": "372c2bf1", + "metadata": {}, + "source": [ + "Payload in raw cell <script>alert('raw cell')</script>" + ] + }, + { + "cell_type": "markdown", + "id": "2d42de4a", + "metadata": {}, + "source": [ + "<script>alert('markdown cell')</script>" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b72e53fa", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "image/svg+xml": ["<script>alert('image/svg+xml output')</script>"] + }, + "execution_count": null, + "metadata": {} + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "64d5d39f", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "svg_filename": "\"><script>alert('svg_filename')</script>", + "data": { + "image/svg+xml": [""] + }, + "execution_count": null, + "metadata": {} + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b72e63fa", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "image/png": [""] + }, + "execution_count": null, + "metadata": { + "filenames": { + "image/png": "\"><script>alert('png filenames')</script>" + } + } + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b72e63f3", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "image/jpeg": [""] + }, + "execution_count": null, + "metadata": { + "filenames": { + "image/jpeg": "\"><script>alert('jpg filenames')</script>" + } + } + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b72e635a", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "image/png": ["\"><script>alert('image/png output')</script>"] + }, + "execution_count": null, + "metadata": {} + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "p72e635a", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "image/jpeg": ["\"><script>alert('image/jpeg output')</script>"] + }, + "execution_count": null, + "metadata": {} + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d72e635a", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "image/png": ["abcd"] + }, + "execution_count": null, + "metadata": { + "width": "><script>alert('output.metadata.width png injection')</script>" + } + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d72e095a", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "image/png": ["abcd"] + }, + "execution_count": null, + "metadata": { + "width": ["><script>alert('output.metadata.width png injection')</script>"] + } + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae4f574d", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "image/png": ["abcd"] + }, + "execution_count": null, + "metadata": { + "height": "><script>alert('output.metadata.height png injection')</script>" + } + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "w72e635a", + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "application/vnd.jupyter.widget-view+json": {"model_id": "wid1", "foo": "\"</script><script>alert('output.data.application/vnd.jupyter.widget-view+json injection')//"} + }, + "execution_count": null, + "metadata": {} + } + ], + "source": [""] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2616e107", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<script>alert('text/html output')</script>" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import os; os.system('touch /tmp/pwned')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "3616e107", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "<script>alert('text/markdown output')</script>" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import os; os.system('touch /tmp/pwned')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "4616e107", + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "alert('application/javascript output')" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import os; os.system('touch /tmp/pwned')" + ] + } + ], + "metadata": { + "title": "TITLE</title><script>alert('title')</script>", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.5" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": {"state": {"wid1": {}}, "foo": "pwntester</script><script>alert('widgets');//"} + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/nbconvert/exporters/tests/test_html.py new/nbconvert-6.5.3/nbconvert/exporters/tests/test_html.py --- old/nbconvert-6.5.0/nbconvert/exporters/tests/test_html.py 2022-04-11 11:07:42.628263000 +0200 +++ new/nbconvert-6.5.3/nbconvert/exporters/tests/test_html.py 2022-08-09 16:16:56.750613000 +0200 @@ -134,3 +134,66 @@ self._get_notebook() ) assert len(output) > 0 + + def test_javascript_injection(self): + for template in ["lab", "classic", "reveal"]: + (output, resources) = HTMLExporter(template_name=template).from_filename( + self._get_notebook("notebook_inject.ipynb") + ) + + # Check injection in the metadata.title of the Notebook + assert "<script>alert('title')</script>" not in output + + # Check injection in the metadata.widgets of the Notebook + assert "</script><script>alert('widgets')" not in output + + # Check injection in the cell.metadata.tags of the Notebook + assert "<script>alert('cell_tag')</script>" not in output + + # Check injection in the cell.source of the Notebook + assert "<script>alert('raw cell')</script>" not in output + + # Check injection in svg output + assert "<script>alert('image/svg+xml output')</script>" not in output + assert "<script>alert('svg_filename')</script>" not in output + + # Check injection in image filenames + assert "<script>alert('png filenames')</script>" not in output + assert "<script>alert('jpg filenames')</script>" not in output + + # Check injection in image data + assert "<script>alert('image/png output')</script>" not in output + assert "<script>alert('image/jpeg output')</script>" not in output + + # Check injection in image width/height + assert "<script>alert('output.metadata.width png injection')</script>" not in output + assert "<script>alert('output.metadata.height png injection')</script>" not in output + + # Check injection in widget view + assert ( + "<script>alert('output.data.application/vnd.jupyter.widget-view+json injection')" + not in output + ) + + # By design, text/html, text/markdown, application/javascript and markdown cells should allow + # for JavaScript code execution + for template in ["lab", "classic", "reveal"]: + (output, resources) = HTMLExporter(template_name=template).from_filename( + self._get_notebook("notebook_inject.ipynb") + ) + + assert "<script>alert('markdown cell')</script>" in output + assert "<script>alert('text/markdown output')</script>" in output + assert "<script>alert('text/html output')</script>" in output + assert "alert('application/javascript output')" in output + + # But it's an opt-out + for template in ["lab", "classic", "reveal"]: + (output, resources) = HTMLExporter( + template_name=template, sanitize_html=True + ).from_filename(self._get_notebook("notebook_inject.ipynb")) + + assert "<script>alert('markdown cell')</script>" not in output + assert "<script>alert('text/markdown output')</script>" not in output + assert "<script>alert('text/html output')</script>" not in output + assert "alert('application/javascript output')" not in output diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/nbconvert/filters/highlight.py new/nbconvert-6.5.3/nbconvert/filters/highlight.py --- old/nbconvert-6.5.0/nbconvert/filters/highlight.py 2022-04-11 11:07:42.629658200 +0200 +++ new/nbconvert-6.5.3/nbconvert/filters/highlight.py 2022-08-09 16:16:56.750613000 +0200 @@ -10,6 +10,7 @@ # because errors should be raised at runtime if it's actually needed, # not import time, when it may not be needed. +from html import escape from warnings import warn from traitlets import observe @@ -67,7 +68,9 @@ return _pygments_highlight( source if len(source) > 0 else " ", # needed to help post processors: - HtmlFormatter(cssclass=" highlight hl-" + language, **self.extra_formatter_options), + HtmlFormatter( + cssclass=escape(f" highlight hl-{language}"), **self.extra_formatter_options + ), language, metadata, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/nbconvert/filters/tests/test_highlight.py new/nbconvert-6.5.3/nbconvert/filters/tests/test_highlight.py --- old/nbconvert-6.5.0/nbconvert/filters/tests/test_highlight.py 2022-04-11 11:07:42.630565400 +0200 +++ new/nbconvert-6.5.3/nbconvert/filters/tests/test_highlight.py 2022-08-09 16:16:56.750613000 +0200 @@ -16,6 +16,8 @@ import xml +import pytest + from ...tests.base import TestsBase from ..highlight import Highlight2HTML, Highlight2Latex @@ -72,6 +74,11 @@ root = xml.etree.ElementTree.fromstring(lang) self.assertEqual(self._extract_tokens(root, "k"), set(tkns)) + @pytest.mark.filterwarnings("ignore") + def test_inject_html(self): + out = highlight2html(self.tests[0], 'ipython3-foo"><script>alert(1)</script>') + assert "<script>alert(1)</script>" not in out + def _extract_tokens(self, root, cls): return set(map(lambda x: x.text, root.findall(".//*[@class='" + cls + "']"))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/nbconvert/nbconvertapp.py new/nbconvert-6.5.3/nbconvert/nbconvertapp.py --- old/nbconvert-6.5.0/nbconvert/nbconvertapp.py 2022-04-11 11:07:42.631174800 +0200 +++ new/nbconvert-6.5.3/nbconvert/nbconvertapp.py 2022-08-11 10:02:47.702777100 +0200 @@ -65,6 +65,7 @@ "template": "TemplateExporter.template_name", "template-file": "TemplateExporter.template_file", "theme": "HTMLExporter.theme", + "sanitize_html": "HTMLExporter.sanitize_html", "writer": "NbConvertApp.writer_class", "post": "NbConvertApp.postprocessor_class", "output": "NbConvertApp.output_base", @@ -178,6 +179,14 @@ }, """Embed the images as base64 dataurls in the output. This flag is only useful for the HTML/WebPDF/Slides exports.""", ), + "sanitize-html": ( + { + "HTMLExporter": { + "sanitize_html": True, + } + }, + """Whether the HTML in Markdown cells and cell outputs should be sanitized..""", + ), } ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/nbconvert/tests/test_nbconvertapp.py new/nbconvert-6.5.3/nbconvert/tests/test_nbconvertapp.py --- old/nbconvert-6.5.0/nbconvert/tests/test_nbconvertapp.py 2022-04-11 11:07:42.638745000 +0200 +++ new/nbconvert-6.5.3/nbconvert/tests/test_nbconvertapp.py 2022-08-09 16:16:56.750613000 +0200 @@ -374,7 +374,7 @@ '<span class="o">=</span> ' '<span class="n">symbols</span>' '<span class="p">(</span>' - '<span class="s1">'x y z'</span>' + "<span class=\"s1\">'x y z'</span>" '<span class="p">)</span>' ) not in text self.nbconvert("notebook1.ipynb --log-level 0 --to html") @@ -392,7 +392,7 @@ '<span class="o">=</span> ' '<span class="n">symbols</span>' '<span class="p">(</span>' - '<span class="s1">'x y z'</span>' + "<span class=\"s1\">'x y z'</span>" '<span class="p">)</span>' ) in text2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/pyproject.toml new/nbconvert-6.5.3/pyproject.toml --- old/nbconvert-6.5.0/pyproject.toml 2022-04-11 11:07:42.640669600 +0200 +++ new/nbconvert-6.5.3/pyproject.toml 2022-08-11 10:02:47.702777100 +0200 @@ -21,5 +21,4 @@ "ignore:unclosed <socket.socket:ResourceWarning", "ignore:unclosed event loop:ResourceWarning", "ignore:There is no current event loop:DeprecationWarning", - ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/setup.py new/nbconvert-6.5.3/setup.py --- old/nbconvert-6.5.0/setup.py 2022-04-11 11:07:42.641157900 +0200 +++ new/nbconvert-6.5.3/setup.py 2022-08-11 10:02:47.702777100 +0200 @@ -237,6 +237,7 @@ ) setup_args["install_requires"] = [ + "lxml", "beautifulsoup4", "bleach", "defusedxml", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/base/celltags.j2 new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/base/celltags.j2 --- old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/base/celltags.j2 2022-04-11 11:07:42.641669000 +0200 +++ new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/base/celltags.j2 2022-08-11 10:02:47.703777000 +0200 @@ -1,7 +1,7 @@ {%- macro celltags(cell) -%} {% if cell.metadata.tags | length > 0 -%} - {% for tag in cell.metadata.tags -%} - {{ ' celltag_' ~ tag -}} + {% for tag in (cell.metadata.tags) -%} + {{ (' celltag_' ~ tag) | escape_html -}} {%- endfor -%} {%- endif %} {%- endmacro %} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/classic/base.html.j2 new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/classic/base.html.j2 --- old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/classic/base.html.j2 2022-04-11 11:07:42.642274600 +0200 +++ new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/classic/base.html.j2 2022-08-11 10:02:47.704777200 +0200 @@ -46,7 +46,7 @@ {% block input %} <div class="inner_cell"> <div class="input_area"> -{{ cell.source | highlight_code(metadata=cell.metadata) }} +{{ cell.source | highlight_code(metadata=cell.metadata) | clean_html }} </div> </div> {%- endblock input %} @@ -81,12 +81,23 @@ {%- endif -%} <div class="inner_cell"> <div class="text_cell_render border-box-sizing rendered_html"> -{{ cell.source | markdown2html | strip_files_prefix }} +{%- if resources.should_sanitize_html %} +{%- set html_value=cell.source | markdown2html | strip_files_prefix | clean_html -%} +{%- else %} +{%- set html_value=cell.source | markdown2html | strip_files_prefix -%} +{%- endif %} +{{ html_value }} </div> </div> </div> {%- endblock markdowncell %} +{% block rawcell scoped %} +{%- if cell.metadata.get('raw_mimetype', '').lower() in resources.get('raw_mimetypes', ['']) -%} +{{ cell.source | clean_html }} +{%- endif -%} +{%- endblock rawcell %} + {% block unknowncell scoped %} unknown type {{ cell.type }} {% endblock unknowncell %} @@ -118,56 +129,66 @@ {% block data_svg scoped -%} <div class="output_svg output_subarea {{ extra_class }}"> {%- if output.svg_filename %} -<img src="{{ output.svg_filename | posix_path }}"> +<img src="{{ output.svg_filename | posix_path | escape_html }}"> {%- else %} -{{ output.data['image/svg+xml'] }} +{{ output.data['image/svg+xml'] | clean_html }} {%- endif %} </div> {%- endblock data_svg %} {% block data_html scoped -%} <div class="output_html rendered_html output_subarea {{ extra_class }}"> +{%- if resources.should_sanitize_html %} +{%- set html_value=output.data['text/html'] | clean_html -%} +{%- else %} +{%- set html_value=output.data['text/html'] -%} +{%- endif %} {%- if output.get('metadata', {}).get('text/html', {}).get('isolated') -%} <iframe class="isolated-iframe" style="height:520px; width:100%; margin:0; padding: 0" frameborder="0" scrolling="auto" - src="data:text/html;base64,{{output.data['text/html'] | text_base64}}"> + src="data:text/html;base64,{{ html_value | text_base64 }}"> </iframe> {%- else -%} -{{ output.data['text/html'] }} +{{ html_value }} {%- endif -%} </div> {%- endblock data_html %} {% block data_markdown scoped -%} +{%- if resources.should_sanitize_html %} +{%- set html_value=output.data['text/markdown'] | markdown2html | clean_html -%} +{%- else %} +{%- set html_value=output.data['text/markdown'] | markdown2html -%} +{%- endif %} <div class="output_markdown rendered_html output_subarea {{ extra_class }}"> -{{ output.data['text/markdown'] | markdown2html }} +{{ html_value }} </div> {%- endblock data_markdown %} {% block data_png scoped %} <div class="output_png output_subarea {{ extra_class }}"> {%- if 'image/png' in output.metadata.get('filenames', {}) %} -<img src="{{ output.metadata.filenames['image/png'] | posix_path }}" +<img src="{{ output.metadata.filenames['image/png'] | posix_path | escape_html }}" {%- else %} -<img src="data:image/png;base64,{{ output.data['image/png'] }}" +<img src="data:image/png;base64,{{ output.data['image/png'] | escape_html }}" {%- endif %} {%- set width=output | get_metadata('width', 'image/png') -%} {%- if width is not none %} -width={{ width }} +width={{ width | escape_html }} {%- endif %} {%- set height=output | get_metadata('height', 'image/png') -%} {%- if height is not none %} -height={{ height }} +height={{ height | escape_html }} {%- endif %} {%- if output | get_metadata('unconfined', 'image/png') %} class="unconfined" {%- endif %} {%- set alttext=(output | get_metadata('alt', 'image/png')) or (cell | get_metadata('alt')) -%} {%- if alttext is not none %} -alt="{{ alttext }}" +alt="{{ alttext | escape_html }}" {%- endif %} > </div> @@ -176,24 +197,24 @@ {% block data_jpg scoped %} <div class="output_jpeg output_subarea {{ extra_class }}"> {%- if 'image/jpeg' in output.metadata.get('filenames', {}) %} -<img src="{{ output.metadata.filenames['image/jpeg'] | posix_path }}" +<img src="{{ output.metadata.filenames['image/jpeg'] | posix_path | escape_html }}" {%- else %} -<img src="data:image/jpeg;base64,{{ output.data['image/jpeg'] }}" +<img src="data:image/jpeg;base64,{{ output.data['image/jpeg'] | escape_html }}" {%- endif %} {%- set width=output | get_metadata('width', 'image/jpeg') -%} {%- if width is not none %} -width={{ width }} +width={{ width | escape_html }} {%- endif %} {%- set height=output | get_metadata('height', 'image/jpeg') -%} {%- if height is not none %} -height={{ height }} +height={{ height | escape_html }} {%- endif %} {%- if output | get_metadata('unconfined', 'image/jpeg') %} class="unconfined" {%- endif %} {%- set alttext=(output | get_metadata('alt', 'image/jpeg')) or (cell | get_metadata('alt')) -%} {%- if alttext is not none %} -alt="{{ alttext }}" +alt="{{ alttext | escape_html }}" {%- endif %} > </div> @@ -228,28 +249,17 @@ {%- block data_javascript scoped %} {% set div_id = uuid4() %} <div id="{{ div_id }}" class="output_subarea output_javascript {{ extra_class }}"> +{%- if not resources.should_sanitize_html %} <script type="text/javascript"> var element = $('#{{ div_id }}'); {{ output.data['application/javascript'] }} </script> +{%- endif %} </div> {%- endblock -%} -{%- block data_widget_state scoped %} -{% set div_id = uuid4() %} -{% set datatype_list = output.data | filter_data_type %} -{% set datatype = datatype_list[0]%} -<div id="{{ div_id }}" class="output_subarea output_widget_state {{ extra_class }}"> -<script type="text/javascript"> -var element = $('#{{ div_id }}'); -</script> -<script type="{{ datatype }}"> -{{ output.data[datatype] | json_dumps }} -</script> -</div> -{%- endblock data_widget_state -%} - {%- block data_widget_view scoped %} +{%- if not resources.should_sanitize_html %} {% set div_id = uuid4() %} {% set datatype_list = output.data | filter_data_type %} {% set datatype = datatype_list[0]%} @@ -258,17 +268,20 @@ var element = $('#{{ div_id }}'); </script> <script type="{{ datatype }}"> -{{ output.data[datatype] | json_dumps }} +{{ output.data[datatype] | json_dumps | escape_html_keep_quotes }} </script> </div> +{%- endif %} {%- endblock data_widget_view -%} {%- block footer %} +{%- if not resources.should_sanitize_html %} {% set mimetype = 'application/vnd.jupyter.widget-state+json'%} {% if mimetype in nb.metadata.get("widgets",{})%} <script type="{{ mimetype }}"> -{{ nb.metadata.widgets[mimetype] | json_dumps | escape_html_script }} +{{ nb.metadata.widgets[mimetype] | json_dumps | escape_html_keep_quotes }} </script> {% endif %} +{%- endif %} {{ super() }} {%- endblock footer-%} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/classic/index.html.j2 new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/classic/index.html.j2 --- old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/classic/index.html.j2 2022-04-11 11:07:42.642428000 +0200 +++ new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/classic/index.html.j2 2022-08-11 13:44:20.857226800 +0200 @@ -9,7 +9,7 @@ {%- block html_head -%} <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> -{% set nb_title = nb.metadata.get('title', '') or resources['metadata']['name'] %} +{% set nb_title = nb.metadata.get('title', resources['metadata']['name']) | escape_html_keep_quotes %} <title>{{nb_title}}</title> {%- block html_head_js -%} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/lab/base.html.j2 new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/lab/base.html.j2 --- old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/lab/base.html.j2 2022-04-11 11:07:42.643566100 +0200 +++ new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/lab/base.html.j2 2022-08-11 10:02:47.704777200 +0200 @@ -26,7 +26,7 @@ {% block input %} <div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline"> <div class="CodeMirror cm-s-jupyter"> -{{ cell.source | highlight_code(metadata=cell.metadata) }} +{{ cell.source | highlight_code(metadata=cell.metadata) | clean_html }} </div> </div> {%- endblock input %} @@ -98,13 +98,24 @@ {{ self.empty_in_prompt() }} {%- endif -%} <div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput {{ celltags(cell) }}" data-mime-type="text/markdown"> -{{ cell.source | markdown2html | strip_files_prefix }} +{%- if resources.should_sanitize_html %} +{%- set html_value=cell.source | markdown2html | strip_files_prefix | clean_html -%} +{%- else %} +{%- set html_value=cell.source | markdown2html | strip_files_prefix -%} +{%- endif %} +{{ html_value }} </div> </div> </div> </div> {%- endblock markdowncell %} +{% block rawcell scoped %} +{%- if cell.metadata.get('raw_mimetype', '').lower() in resources.get('raw_mimetypes', ['']) -%} +{{ cell.source | clean_html }} +{%- endif -%} +{%- endblock rawcell %} + {% block unknowncell scoped %} unknown type {{ cell.type }} {% endblock unknowncell %} @@ -146,39 +157,48 @@ {% block data_svg scoped -%} <div class="jp-RenderedSVG jp-OutputArea-output {{ extra_class }}" data-mime-type="image/svg+xml"> {%- if output.svg_filename %} -<img src="{{ output.svg_filename | posix_path }}"> +<img src="{{ output.svg_filename | posix_path | escape_html }}"> {%- else %} -{{ output.data['image/svg+xml'] }} +{{ output.data['image/svg+xml'] | clean_html }} {%- endif %} </div> {%- endblock data_svg %} {% block data_html scoped -%} <div class="jp-RenderedHTMLCommon jp-RenderedHTML jp-OutputArea-output {{ extra_class }}" data-mime-type="text/html"> +{%- if resources.should_sanitize_html %} +{{ output.data['text/html'] | clean_html }} +{%- else %} {{ output.data['text/html'] }} +{%- endif %} </div> {%- endblock data_html %} {% block data_markdown scoped -%} +{%- if resources.should_sanitize_html %} +{%- set html_value=output.data['text/markdown'] | markdown2html | clean_html -%} +{%- else %} +{%- set html_value=output.data['text/markdown'] | markdown2html -%} +{%- endif %} <div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-OutputArea-output {{ extra_class }}" data-mime-type="text/markdown"> -{{ output.data['text/markdown'] | markdown2html }} +{{ html_value }} </div> {%- endblock data_markdown %} {% block data_png scoped %} <div class="jp-RenderedImage jp-OutputArea-output {{ extra_class }}"> {%- if 'image/png' in output.metadata.get('filenames', {}) %} -<img src="{{ output.metadata.filenames['image/png'] | posix_path }}" +<img src="{{ output.metadata.filenames['image/png'] | posix_path | escape_html }}" {%- else %} -<img src="data:image/png;base64,{{ output.data['image/png'] }}" +<img src="data:image/png;base64,{{ output.data['image/png'] | escape_html }}" {%- endif %} {%- set width=output | get_metadata('width', 'image/png') -%} {%- if width is not none %} -width={{ width }} +width={{ width | escape_html }} {%- endif %} {%- set height=output | get_metadata('height', 'image/png') -%} {%- if height is not none %} -height={{ height }} +height={{ height | escape_html }} {%- endif %} class=" {%- if output | get_metadata('unconfined', 'image/png') %} @@ -198,17 +218,17 @@ {% block data_jpg scoped %} <div class="jp-RenderedImage jp-OutputArea-output {{ extra_class }}"> {%- if 'image/jpeg' in output.metadata.get('filenames', {}) %} -<img src="{{ output.metadata.filenames['image/jpeg'] | posix_path }}" +<img src="{{ output.metadata.filenames['image/jpeg'] | posix_path | escape_html }}" {%- else %} -<img src="data:image/jpeg;base64,{{ output.data['image/jpeg'] }}" +<img src="data:image/jpeg;base64,{{ output.data['image/jpeg'] | escape_html }}" {%- endif %} {%- set width=output | get_metadata('width', 'image/jpeg') -%} {%- if width is not none %} -width={{ width }} +width={{ width | escape_html }} {%- endif %} {%- set height=output | get_metadata('height', 'image/jpeg') -%} {%- if height is not none %} -height={{ height }} +height={{ height | escape_html }} {%- endif %} class=" {%- if output | get_metadata('unconfined', 'image/jpeg') %} @@ -260,27 +280,15 @@ {% set div_id = uuid4() %} {%- block data_javascript scoped %} <div id="{{ div_id }}" class="jp-RenderedJavaScript jp-OutputArea-output {{ extra_class }}" data-mime-type="application/javascript"> +{%- if not resources.should_sanitize_html %} <script type="text/javascript"> var element = document.getElementById('{{ div_id }}'); {{ output.data['application/javascript'] }} </script> +{%- endif %} </div> {%- endblock -%} -{%- block data_widget_state scoped %} -{% set div_id = uuid4() %} -{% set datatype_list = output.data | filter_data_type %} -{% set datatype = datatype_list[0]%} -<div id="{{ div_id }}" class="output_subarea output_widget_state {{ extra_class }}"> -<script type="text/javascript"> -var element = document.getElementById('{{ div_id }}'); -</script> -<script type="{{ datatype }}"> -{{ output.data[datatype] | json_dumps }} -</script> -</div> -{%- endblock data_widget_state -%} - {%- block data_widget_view scoped %} {% set div_id = uuid4() %} {% set datatype_list = output.data | filter_data_type %} @@ -290,7 +298,7 @@ var element = document.getElementById('{{ div_id }}'); </script> <script type="{{ datatype }}"> -{{ output.data[datatype] | json_dumps }} +{{ output.data[datatype] | json_dumps | escape_html_keep_quotes }} </script> </div> {%- endblock data_widget_view -%} @@ -299,7 +307,7 @@ {% set mimetype = 'application/vnd.jupyter.widget-state+json'%} {% if mimetype in nb.metadata.get("widgets",{})%} <script type="{{ mimetype }}"> -{{ nb.metadata.widgets[mimetype] | json_dumps | escape_html_script }} +{{ nb.metadata.widgets[mimetype] | json_dumps | escape_html_keep_quotes }} </script> {% endif %} {{ super() }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/lab/index.html.j2 new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/lab/index.html.j2 --- old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/lab/index.html.j2 2022-04-11 11:07:42.643724200 +0200 +++ new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/lab/index.html.j2 2022-08-11 13:44:20.857226800 +0200 @@ -9,7 +9,7 @@ {%- block html_head -%} <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> -{% set nb_title = nb.metadata.get('title', '') or resources['metadata']['name'] %} +{% set nb_title = nb.metadata.get('title', resources['metadata']['name']) | escape_html_keep_quotes %} <title>{{nb_title}}</title> {%- block html_head_js -%} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/reveal/index.html.j2 new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/reveal/index.html.j2 --- old/nbconvert-6.5.0/share/jupyter/nbconvert/templates/reveal/index.html.j2 2022-04-11 11:07:42.645413200 +0200 +++ new/nbconvert-6.5.3/share/jupyter/nbconvert/templates/reveal/index.html.j2 2022-08-11 13:44:20.857226800 +0200 @@ -20,7 +20,7 @@ <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> -{% set nb_title = nb.metadata.get('title', '') or resources['metadata']['name'] %} +{% set nb_title = nb.metadata.get('title', resources['metadata']['name']) | escape_html_keep_quotes %} <title>{{nb_title}} slides</title> {%- block html_head_js -%} ++++++ nbconvert-vendorize-mistune.patch ++++++ --- /var/tmp/diff_new_pack.3Q8kk1/_old 2022-08-11 18:33:18.478198756 +0200 +++ /var/tmp/diff_new_pack.3Q8kk1/_new 2022-08-11 18:33:18.478198756 +0200 @@ -1,7 +1,7 @@ -Index: nbconvert-6.5.0/nbconvert/filters/markdown_mistune.py +Index: nbconvert-6.5.3/nbconvert/filters/markdown_mistune.py =================================================================== ---- nbconvert-6.5.0.orig/nbconvert/filters/markdown_mistune.py -+++ nbconvert-6.5.0/nbconvert/filters/markdown_mistune.py +--- nbconvert-6.5.3.orig/nbconvert/filters/markdown_mistune.py ++++ nbconvert-6.5.3/nbconvert/filters/markdown_mistune.py @@ -21,7 +21,9 @@ except ImportError: from cgi import escape as html_escape @@ -13,10 +13,10 @@ from pygments import highlight from pygments.formatters import HtmlFormatter from pygments.lexers import get_lexer_by_name -Index: nbconvert-6.5.0/setup.py +Index: nbconvert-6.5.3/setup.py =================================================================== ---- nbconvert-6.5.0.orig/setup.py -+++ nbconvert-6.5.0/setup.py +--- nbconvert-6.5.3.orig/setup.py ++++ nbconvert-6.5.3/setup.py @@ -245,7 +245,6 @@ setup_args["install_requires"] = [ "jupyter_core>=4.7", "jupyterlab_pygments",