From 566de65f17c3e7a939c8a856231791f6935accee Mon Sep 17 00:00:00 2001 From: ed Date: Mon, 17 Aug 2026 21:04:45 +0000 Subject: [PATCH] option to allow js in svg --- copyparty/__main__.py | 1 + copyparty/cfg.py | 2 ++ copyparty/httpcli.py | 9 +++++++-- tests/util.py | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 6971c813..3b68980f 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1679,6 +1679,7 @@ def add_yolo(ap): ap2 = ap.add_argument_group("yolo options") ap2.add_argument("--allow-csrf", action="store_true", help="disable csrf protections; let other domains/sites impersonate you through cross-site requests; \033[1;31mDANGEROUS\033[0m / LAN-only") ap2.add_argument("--cookie-lax", action="store_true", help="allow cookies from other domains (if you follow a link from another website into your server, you will arrive logged-in); this reduces protection against CSRF") + ap2.add_argument("--allow-svg-js", action="store_true", help="allow svg images to execute javascript; default-disabled because ~nobody wants it (volflag=allow_svg_js)") ap2.add_argument("--no-fnugg", action="store_true", help="disable the smoketest for caching-related issues in the web-UI") ap2.add_argument("--getmod", action="store_true", help="permit ?move=[...] and ?delete as GET -- \033[1;31mDANGEROUS\033[0m, removes csrf protection") ap2.add_argument("--wo-up-readme", action="store_true", help="allow users with write-only access to upload logues and readmes without adding the _wo_ filename prefix (volflag=wo_up_readme)") diff --git a/copyparty/cfg.py b/copyparty/cfg.py index 930ec356..ec832a3e 100644 --- a/copyparty/cfg.py +++ b/copyparty/cfg.py @@ -33,6 +33,7 @@ def vf_bmap() -> dict[str, str]: "vol_or_crash": "assert_root", } for k in ( + "allow_svg_js", "dedup", "dlni", "dothidden", @@ -386,6 +387,7 @@ flagcats = { "csp_dl": "content-security-policy for static files", "nohtml": "return html and markdown as text/html", "noscript": "disable most javascript by use of CSP", + "allow_svg_js": "allow javascript in svg images", "ui_noacci": "hide account-info in the UI", "ui_nocpla": "hide cpanel-link in the UI", "ui_nolbar": "hide link-bar in the UI", diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index a8e5da8e..44aafda9 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -5040,8 +5040,13 @@ class HttpCli(object): else: mime = guess_mime(cdis) - if mime not in SAFE_MIMES and "nohtml" in self.vn.flags and oh_k != "oh_g": - mime = safe_mime(mime) + if mime not in SAFE_MIMES: + if "nohtml" in self.vn.flags and oh_k != "oh_g": + mime = safe_mime(mime) + elif mime == "image/svg+xml" and "allow_svg_js" not in self.vn.flags: + oh_k = "oh_g" + if "nonce-" not in self.vn.flags[oh_k]: + mime = safe_mime(mime) self.out_headers["Accept-Ranges"] = "bytes" logmsg += unicode(status) + logtail diff --git a/tests/util.py b/tests/util.py index 79504e18..7a72fcb3 100644 --- a/tests/util.py +++ b/tests/util.py @@ -145,7 +145,7 @@ class Cfg(Namespace): def __init__(self, a=None, v=None, c=None, **ka0): ka = {} - ex = "allow_flac allow_wav chpw cookie_lax daw dav_auth dav_mac dav_rt dlni dothidden e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp early_ban ed emp exp force_js getmod grid gsel hardlink hardlink_only http_no_tcp ih ihead localtime log_badxml magic md_no_br nid nih no_acode no_athumb no_bauth no_clone no_cp no_dav no_db_ip no_del no_dirsz no_dupe no_dupe_m no_fnugg no_html no_lifetime no_logues no_mv no_pipe no_poll no_readme no_robots no_sb_md no_sb_lg no_scandir no_script no_tail no_tarcmp no_thumb no_vthumb no_u2abrt no_zip no_zls nrand nsort nw og og_no_head og_s_title ohead opds q rand re_dirsz reflink rm_partial rmagic rss show_hist smb srch_dbg srch_excl srch_icase stats ui_noacci ui_nocpla ui_noctxb ui_nolbar ui_nombar ui_nonav ui_notree ui_norepl ui_nosrvi uqe usernames vague_403 vc ver vol_nospawn vol_or_crash wo_up_readme wopi write_uplog xdev xlink xvol zipmaxu zs" + ex = "allow_flac allow_wav allow_svg_js chpw cookie_lax daw dav_auth dav_mac dav_rt dlni dothidden e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp early_ban ed emp exp force_js getmod grid gsel hardlink hardlink_only http_no_tcp ih ihead localtime log_badxml magic md_no_br nid nih no_acode no_athumb no_bauth no_clone no_cp no_dav no_db_ip no_del no_dirsz no_dupe no_dupe_m no_fnugg no_html no_lifetime no_logues no_mv no_pipe no_poll no_readme no_robots no_sb_md no_sb_lg no_scandir no_script no_tail no_tarcmp no_thumb no_vthumb no_u2abrt no_zip no_zls nrand nsort nw og og_no_head og_s_title ohead opds q rand re_dirsz reflink rm_partial rmagic rss show_hist smb srch_dbg srch_excl srch_icase stats ui_noacci ui_nocpla ui_noctxb ui_nolbar ui_nombar ui_nonav ui_notree ui_norepl ui_nosrvi uqe usernames vague_403 vc ver vol_nospawn vol_or_crash wo_up_readme wopi write_uplog xdev xlink xvol zipmaxu zs" ka.update(**{k: False for k in ex.split()}) ex = "dav_inf dedup dotpart dotsrch hook_v no_dhash no_fastboot no_fpool no_htp no_rescan no_sendfile no_ses no_snap no_up_list no_voldump wram re_dhash see_dots plain_ip"