diff --git a/cps/epub.py b/cps/epub.py index 3947cee65..638462f09 100644 --- a/cps/epub.py +++ b/cps/epub.py @@ -175,7 +175,7 @@ def parse_epub_cover(ns, tree, epub_zip, cover_path, tmp_file_path): for cs in cover_section: if cs.endswith('.xhtml') or cs.endswith('.html'): markup = epub_zip.read(os.path.join(cover_path, cs)) - markup_tree = etree.fromstring(markup) + markup_tree = etree.fromstring(markup, parser=etree.XMLParser(resolve_entities=False, no_network=True)) # no matter xhtml or html with no namespace img_src = markup_tree.xpath("//*[local-name() = 'img']/@src") # Alternative image source diff --git a/cps/epub_helper.py b/cps/epub_helper.py index 4517f2c60..252fad313 100644 --- a/cps/epub_helper.py +++ b/cps/epub_helper.py @@ -53,16 +53,20 @@ def updateEpub(src, dest, filename, data, ): zf.writestr(filename, data) +# Safe parser: disable entity resolution and network access to prevent XXE attacks +_safe_parser = etree.XMLParser(resolve_entities=False, no_network=True) + + def get_content_opf(file_path, ns=None): if ns is None: ns = default_ns epubZip = zipfile.ZipFile(file_path) txt = epubZip.read('META-INF/container.xml') - tree = etree.fromstring(txt) + tree = etree.fromstring(txt, parser=_safe_parser) cf_name = tree.xpath('n:rootfiles/n:rootfile/@full-path', namespaces=ns)[0] cf = epubZip.read(cf_name) - return etree.fromstring(cf), cf_name + return etree.fromstring(cf, parser=_safe_parser), cf_name def create_new_metadata_backup(book, custom_columns, export_language, translated_cover_name, lang_type=3): diff --git a/cps/fb2.py b/cps/fb2.py index 81eae579f..12ccbc1ca 100644 --- a/cps/fb2.py +++ b/cps/fb2.py @@ -20,6 +20,9 @@ from lxml import etree from .constants import BookMeta +# Safe parser: disable entity resolution and network access to prevent XXE attacks +_safe_parser = etree.XMLParser(resolve_entities=False, no_network=True) + def get_fb2_info(tmp_file_path, original_file_extension): @@ -29,7 +32,7 @@ def get_fb2_info(tmp_file_path, original_file_extension): } fb2_file = open(tmp_file_path, encoding="utf-8") - tree = etree.fromstring(fb2_file.read().encode()) + tree = etree.fromstring(fb2_file.read().encode(), parser=_safe_parser) authors = tree.xpath('/fb:FictionBook/fb:description/fb:title-info/fb:author', namespaces=ns) diff --git a/cps/services/goodreads_support.py b/cps/services/goodreads_support.py index 06b218bf8..eec85b5b2 100644 --- a/cps/services/goodreads_support.py +++ b/cps/services/goodreads_support.py @@ -92,7 +92,7 @@ class my_GoodreadsRequest(GoodreadsRequest): if resp.status_code != 200: raise GoodreadsRequestException(resp.reason, self.path) if self.req_format == 'xml': - root = etree.fromstring(resp.content) + root = etree.fromstring(resp.content, parser=etree.XMLParser(resolve_entities=False, no_network=True)) data_dict = etree_to_dict(root) return data_dict['GoodreadsResponse']