···285285The typical security aspect discussed for markdown is [cross-site scripting
286286(XSS)][xss] attacks.
287287Markdown itself is safe if it does not include embedded HTML or dangerous
288288-protocols in links/images (such as `javascript:` or `data:`).
288288+protocols in links/images (such as `javascript:`).
289289`markdown-rs` makes any markdown safe by default, even if HTML is embedded or
290290dangerous protocols are used, as it encodes or drops them.
291291+291292Turning on the `allow_dangerous_html` or `allow_dangerous_protocol` options for
292293user-provided markdown opens you up to XSS attacks.
294294+295295+Additionnally, you should be able to set `allow_any_img_src` safely.
296296+The default is to allow only `http:`, `https:`, and relative images,
297297+which is what GitHub does. But it should be safe to allow any value on `src`.
298298+299299+The [HTML specification][whatwg-html-image] prohibits dangerous scripts in
300300+images and all modern browsers respect this and are thus safe.
301301+Opera 12 (from 2012) is a notable browser that did not respect this.
293302294303An aspect related to XSS for security is syntax errors: markdown itself has no
295304syntax errors.
···413422[support]: .github/support.md
414423415424[coc]: .github/code-of-conduct.md
425425+426426+[whatwg-html-image]: https://html.spec.whatwg.org/multipage/images.html#images-processing-model
+59
src/configuration.rs
···522522 /// `ircs`, `mailto`, `xmpp`), are safe.
523523 /// All other URLs are dangerous and dropped.
524524 ///
525525+ /// When the option `allow_all_protocols_in_img` is enabled,
526526+ /// `allow_dangerous_protocol` only applies to links.
527527+ ///
528528+ /// This is safe because the
529529+ /// [HTML specification][whatwg-html-image-processing]
530530+ /// does not allow executable code in images.
531531+ /// All modern browsers respect this.
532532+ ///
533533+ /// [whatwg-html-image-processing]: https://html.spec.whatwg.org/multipage/images.html#images-processing-model
534534+ ///
525535 /// ## Examples
526536 ///
527537 /// ```
···552562 /// # }
553563 /// ```
554564 pub allow_dangerous_protocol: bool,
565565+566566+ /// Whether to allow all values in images.
567567+ ///
568568+ /// The default is `false`,
569569+ /// which lets `allow_dangerous_protocol` control protocol safety for
570570+ /// both links and images.
571571+ ///
572572+ /// Pass `true` to allow all values as `src` on images,
573573+ /// regardless of `allow_dangerous_protocol`.
574574+ /// This is safe because the
575575+ /// [HTML specification][whatwg-html-image-processing]
576576+ /// does not allow executable code in images.
577577+ ///
578578+ /// [whatwg-html-image-processing]: https://html.spec.whatwg.org/multipage/images.html#images-processing-model
579579+ ///
580580+ /// ## Examples
581581+ ///
582582+ /// ```
583583+ /// use markdown::{to_html_with_options, CompileOptions, Options};
584584+ /// # fn main() -> Result<(), markdown::message::Message> {
585585+ ///
586586+ /// // By default, some protocols in image sources are dropped:
587587+ /// assert_eq!(
588588+ /// to_html_with_options(
589589+ /// "",
590590+ /// &Options::default()
591591+ /// )?,
592592+ /// "<p><img src=\"\" alt=\"\" /></p>"
593593+ /// );
594594+ ///
595595+ /// // Turn `allow_any_img_src` on to allow all values as `src` on images.
596596+ /// // This is safe because browsers do not execute code in images.
597597+ /// assert_eq!(
598598+ /// to_html_with_options(
599599+ /// ")",
600600+ /// &Options {
601601+ /// compile: CompileOptions {
602602+ /// allow_any_img_src: true,
603603+ /// ..CompileOptions::default()
604604+ /// },
605605+ /// ..Options::default()
606606+ /// }
607607+ /// )?,
608608+ /// "<p><img src=\"javascript:alert(1)\" alt=\"\" /></p>"
609609+ /// );
610610+ /// # Ok(())
611611+ /// # }
612612+ /// ```
613613+ pub allow_any_img_src: bool,
555614556615 // To do: `doc_markdown` is broken.
557616 #[allow(clippy::doc_markdown)]
+4-1
src/to_html.rs
···14571457 };
1458145814591459 if let Some(destination) = destination {
14601460- let url = if context.options.allow_dangerous_protocol {
14601460+ let allow_dangerous_protocol = context.options.allow_dangerous_protocol
14611461+ || (context.options.allow_any_img_src && media.image);
14621462+14631463+ let url = if allow_dangerous_protocol {
14611464 sanitize(destination)
14621465 } else {
14631466 sanitize_with_protocols(