diff --git a/CHANGES.md b/CHANGES.md
index afb0be54..a77bd029 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -27,6 +27,7 @@
- [pull #743] Add a `strip-syntax` option to the `header-ids` extra that leaves link URLs, image paths, inline HTML tags and emphasis markers out of header ids (#192)
- [pull #747] Fix `link-patterns` extra linking text inside Markdown links and images whose label wraps onto another line
- [pull #759] Fix `fenced-code-blocks` extra not recognizing code blocks whose language name contains `#` or `.`, such as `c#`, `f#` and `vb.net`
+- [pull #766] Fix `safe_mode` allowing `javascript:` and other unsafe URLs in image sources (#764)
## python-markdown2 2.5.5
diff --git a/lib/markdown2.py b/lib/markdown2.py
index e35bf5d2..0e13c689 100755
--- a/lib/markdown2.py
+++ b/lib/markdown2.py
@@ -3248,6 +3248,17 @@ def process_image(self, url: str, title_attr: str, link_text: str) -> Tuple[str,
2. The length of the opening HTML tag in the string. For `` it's the whole string.
This section will be skipped by the link processor
'''
+ if self.md.safe_mode and not self.md._safe_href.match(url):
+ # same check as links, but keep allowing base64 image data URLs
+ data_url = self.md._data_url_re.match(url)
+ if not (
+ data_url
+ and (data_url.group('mime') or '').startswith('image/')
+ and data_url.group('token') == ';base64'
+ and re.fullmatch(r'[A-Za-z0-9+/=]*', data_url.group('data'))
+ ):
+ url = '#'
+
img_class_str = self.md._html_class_str_from_tag("img")
result = (
f'

<img src="javascript:alert(1)"
diff --git a/test/tm-cases/image_safe_urls.html b/test/tm-cases/image_safe_urls.html new file mode 100644 index 00000000..5517dfe2 --- /dev/null +++ b/test/tm-cases/image_safe_urls.html @@ -0,0 +1,25 @@ +


+
<x><svg onload=alert(origin)
<x><svg onload=alert(origin)
Code spans still come out escaped once: a<b, <b> and C:\<folder>
http://onclick=alert(origin)//
http://onclick=alert(origin)//[<codeClick me]()>
-![x](<"`"
![x](<"`"