Skip to main content

safemd Twitter Follow Add Hultnér on LinkedIn Build Status PyPI - Status Codacy Badge Codacy Badge PyPI Code style: black

♜ safemd

A markdown renderer focusing on security first
Building upon the strong foundation of GitHub's fork of cmark while adding additional security precautions to be safe out of the box.

When auditing applications rendering markdown from user input I noticed that many popular markdown implementations are unsafe and vulnerable to XSS with standard configuration.

I am a strong believer in safe by default instead of opt-in security. Therefor I decided to build a library focusing on using the best tools for the job while configuring them to safely render unsanitized user input.

Installation & usage

Install through pip:
Any other tool using PyPI works fine as well, I always recommend using virtual environments.

$ pip install safemd

Render standard markdown:

import safemd

safemd.render(content)

Render GitHub Flavoured Markdown:

import safemd

safemd.render(content, flavour="github")

Precautions taken

The same library used for rendering markdown in the official PyPI Warehouse application is used by safemd. This is based on GitHub's battle-tested fork of CommonMark. We use this with the safety feature CMARK_OPT_SAFE enabled per default, so no one in your team accidentally let insecure code slip through. As an additional safety layer safemd also pass the output from cmark through a whitelist with Bleach, Mozilla's HTML sanitizing library.

Automatic safety testing through Travis is also utilized, running daily even if there are no new changes.

Opt-out from safety features

There's a way to opt-out of these safety precautions for those cases where you have a genuine need, this way it's obvious for you and your team that these places are to be considered with extra care.

import safemd

# Disable additional whitelist sanitizing through bleach
safemd.render(content, UNSAFE_NO_BLEACH=True)

# Disable cmark safety functions
safemd.render(content, UNSAFE_CMARK_XSS=True)

Is my application vulnerable?

It's not uncommon for various markdown-renderers in production environments to be open for XSS-exploits, some more widespread than others. A list of common exploits have been assembled for your convenience, so you can test your current and future code.

[Just a link](javascript:alert("hi"))

[Normal link](data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGkiKTwvc2NyaXB0Pgo=) 

[Nothing fishy here](data:text/html;base64,PHNjcmlwdCBzcmM9Imh0dHBzOi8vZ2lzdGNkbi5naXRoYWNrLmNvbS9IdWx0bmVyL2JjMDIzOGJkOWIxZDI4M2JhMWM5NDczZjU0M2ZmZjc4L3Jhdy9kM2U5YWFkYTdlMGRlNzFkNmNlYTY1MDVmMTljZGE2NjE1MmE0MDFlL2hpLmpzIiBpbnRlZ3JpdHk9InNoYTM4NC0yaGZ6aFlkelB1SGd0S1E2Vk96UGlNbEN2Nzl3WDM1NzdxTDR3eWpmNWhMYkEvcW1BZHhCbXdxNGl6YXRwRy93IiBjcm9zc29yaWdpbj0iYW5vbnltb3VzIj48L3NjcmlwdD4=)

Markdown XSS exploits found in the wild

Of course, this document wouldn't be complete without a list of markdown-based XSS-exploits found in the wild. Most of these are from 2018 and 2017.

Found something

I am grateful for all suggestions, improvements and bugfixes. Feel free to send a PR or create a GitHub Issue for anything that isn't sensitive and urgent. Additional tests trying to break the security is especially appriciated.

I'm on keybase for encrypted communication. Send an email to security on my own domain hultner.se. Be aware, I discard any SPF, DMARC or DKIM-failing message, including SPF-Soft fail.


 .
..:

Metadata

Release files for safemd 19.10.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for safemd 19.10.1
File Size Uploaded
safemd-19.10.1.tar.gz 6.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for safemd 19.10.1
File Interpreter ABI Platform
safemd-19.10.1-py3-none-any.whl Python 3 none any Details

Total release size: 15.5 kB

Release files / safemd-19.10.1.tar.gz

Download URL safemd-19.10.1.tar.gz
Size 6.6 kB
Tags Source
SHA-256 checksum
How to use checksums
0393934fb81a0755a988894f0b0c4bd23a7249fb3722ac1e1dfc6c4513af6aaa
BLAKE2b-256 checksum
How to use checksums
529acdecb0184101e6e75befa0ad6fd27397a1425c4796d2a296370aa60c0c2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/2.0.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.36.1 CPython/3.7.4

Release files / safemd-19.10.1-py3-none-any.whl

Download URL safemd-19.10.1-py3-none-any.whl
Size 8.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
006ba3f0f9fe8046c3e4a62a06c9d371df4511624195cfd7323cdc0785f8d5c5
BLAKE2b-256 checksum
How to use checksums
5d0a3a3381969b39fba7b50bd13834a1a7207951a0712e6360f9fb2ee29fb51d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/2.0.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.36.1 CPython/3.7.4

Release history Release notifications | RSS feed

This release

19.10.1 This release

2 release files

18.10

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page