Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Safe Mode #161

Closed
clphillips opened this issue Apr 29, 2014 · 44 comments · Fixed by #495
Closed

Safe Mode #161

clphillips opened this issue Apr 29, 2014 · 44 comments · Fixed by #495

Comments

@clphillips
Copy link

Parsedown offers no safe option for rendering, so, for those of us who allow no HTML content within markdown text, we must sanitize prior to feeding to Parsedown. As a result, Parsedown double encodes HTML entities (see #50).

Instead, Parsedown should offer a "safe" option.

function text($text, $safe_mode = false) {
    $this->safe_mode = $safe_mode;
    if ($safe_mode) {
        $text = htmlentities($text, ENT_QUOTES, 'UTF-8');
    }
    ...
}

Usage:

$parsedown = new ParseDown();
$text = "<script>alert('unsafe text');</script>";
echo $parsedown->text($text, true);

Output:

&lt;script&gt;alert(&quote;unsafe text&quote;);&lt/script&gt;
@clphillips
Copy link
Author

Also,

protected function identifyLink($excerpt)
{
    ...
    $url = $Link['url'];//str_replace(array('&', '<'), array('&amp;', '&lt;'), $Link['url']);
    ...

Should take into consideration safe_mode, and ignore this replacement.

@hkdobrev
Copy link
Contributor

@clphillips Do you actually want Parsedown to have HTML-free mode?

@clphillips
Copy link
Author

@hkdobrev Yes. HTML-free in terms of not allowing HTML content from untrusted users. In many cases the only HTML I want is what is produced by markdown flavored plain-text.

I'm actually hard pressed to find a single situation where I would actually want HTML content intermingled in my markdown text.

@apfelbox
Copy link
Contributor

apfelbox commented May 5, 2014

This is an absolute requirement to use this library as renderer for user-entered content.

@cebe
Copy link
Contributor

cebe commented May 5, 2014

you should use something like HTML purifier to extract all elements you do not want from the produced markdown.

@clphillips
Copy link
Author

@cebe Uh, no we shouldn't. HTML purifier is extremely slow, and is a ridiculous solution for something that can be solved with 5 lines of code in this library.

@apfelbox
Copy link
Contributor

apfelbox commented May 5, 2014

@cebe there is absolutely no need to parse a huge DOM tree with a very complex library, when a simple text search & replace is sufficient. This is just waisting resources (and PHP is not exactly the fastest language available, so...).

Maybe we should also include securing link destinations:

[hi there](javascript:alert('hi there'))

@erusev
Copy link
Owner

erusev commented May 5, 2014

I agree that it might make sense for Parsedown to do some sanitisation. It doesn't have to, but since it already knows so much about the texts it parses, it might not be too hard.

@clphillips
Copy link
Author

Just for reference, other popular markdown libraries (for other languages) also support a "safe mode". See Python-Markdown and MarkdownDeep, for example.

Will try to update this issue with a pull request with the changes I've made when I get a chance.

@erusev
Copy link
Owner

erusev commented May 5, 2014

@clphillips Thanks. I'll check them out.

@cebe
Copy link
Contributor

cebe commented May 5, 2014

I agree that the markdown parser can do it more easily.

@stewartlord
Copy link

Just adding fuel to the fire. Hoping to use Parsedown, but this is a blocker for me. I would also like to avoid using HTML Purifier for performance and licensing reasons. Happy to lend a hand.

@xPaw
Copy link
Contributor

xPaw commented May 25, 2014

👍 Would also like to see safe mode.

@stewartlord
Copy link

Anyone started on this or are we looking for volunteers?

On May 25, 2014, at 10:15 AM, Pavel notifications@github.com wrote:

Would also like to see safe mode.


Reply to this email directly or view it on GitHub.

@erusev
Copy link
Owner

erusev commented May 26, 2014

I'm working on it.

@stewartlord
Copy link

Awesome! 👍

On May 26, 2014, at 10:31 AM, Emanuil Rusev notifications@github.com wrote:

I'm working on it.


Reply to this email directly or view it on GitHub.

@xPaw
Copy link
Contributor

xPaw commented Aug 9, 2014

I'm still waiting for this to be implemented before I can deploy parsedown on my website. Is there any progress?

@erusev erusev added the priority label Aug 9, 2014
@erusev erusev changed the title Add option to disable htmlspecialchars in code blocks Safe Mode Aug 9, 2014
@erusev
Copy link
Owner

erusev commented Aug 16, 2014

Could we come up with a simple specification?

@xPaw
Copy link
Contributor

xPaw commented Aug 16, 2014

Either have a whitelist of allowed elements (like ) and escape other elements, or just escape all html tags.

@erusev
Copy link
Owner

erusev commented Aug 16, 2014

@xPaw This alone would not make the output safe. It's more complicated than that. What would we do with things like [link](javascript:alert('xss'))?

There's a related discussion at http://security.stackexchange.com/questions/14664/how-do-i-use-markdown-securely.

@xPaw
Copy link
Contributor

xPaw commented Aug 16, 2014

Indeed urls have to be escaped as well. (shouldn't this already be done regardless of safe mode?)

@hkdobrev
Copy link
Contributor

I suggest to have several setters for disabling certain functionality. One of them would disable usage of HTML in the Markdown. Another could be about XSS.

Then we could have a setter for safe-mode which will set several of those setters.

I am suggesting this approach, because some would want HTML-free mode without messing with parsing of URLs or images.

@markseuffert
Copy link

markseuffert commented Oct 9, 2014

Good to hear a safe mode is in the works.

I am currently using Michel Fortin's Markdown parser and have done the following to prevent XSS: Disable HTML tags and entities, which escapes meta characters < and &. Filter Markdown generated URLs via callback url_filter_func(), which filters out unsafe things that are not on a whitelist. Then we tried to inject code with obfuscation and random data. A list of test cases can be found here: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

Edit: Updated link

@ckzhou
Copy link

ckzhou commented Mar 10, 2015

[xss](http://"onmouseover="alert(1))

This vector can pop a alert box in firefox!

@xorock
Copy link

xorock commented Aug 12, 2015

For several years I used Textile https://github.com/textile/php-textile and there is textileRestricted method which is suitable for untrusted input. As I understand there is no such thing in this library?

@erusev
Copy link
Owner

erusev commented Aug 13, 2015

Would someone like to create a simple set of test data that includes .md and .html files with input and expected safe output?

@clphillips
Copy link
Author

@erusev You want that as a PR, or what? Examples here: XSS Filter Evasion Cheat Sheet.

@erusev
Copy link
Owner

erusev commented Aug 13, 2015

@clphillips Sure, but let's start simple. We could start with 5 to 10 pairs to see if this test driven approach would work.

@erusev
Copy link
Owner

erusev commented Aug 17, 2015

@dariuszp
Copy link

Hi, any ETA on this? I need markdown in my latest project. I was thinking of using parsedown but it will be for user generated content.
Because of this issue I had to abandon this library.

@BboyKeen
Copy link

I'm interested too. Any news for the safe mode ?

@erusev
Copy link
Owner

erusev commented Dec 5, 2015

I've been thinking about this and I do plan to start implementing it, hopefully, in January.

@hootlex
Copy link

hootlex commented Jul 22, 2016

any update on this?

@erusev
Copy link
Owner

erusev commented Jul 25, 2016

Not yet, but perhaps soon.

@hootlex
Copy link

hootlex commented Jul 26, 2016

Great, looking forward.

@Penagwin
Copy link

Is there any word on this right now?

@m1guelpf
Copy link
Contributor

Updates?

@erusev
Copy link
Owner

erusev commented Apr 30, 2017

Not yet, it's taking me some time :(

@sdkcarlos
Copy link

Well, for me worked perfectly by using the setMarkupEscaped option to true:

$markdown = "The markdown of the following image ... ";

$Parsedown = new Parsedown();

$Parsedown->setMarkupEscaped(true);

echo $Parsedown->text($markdown);

For example, the following markdown:

image

Would display in the browser the second alert if the setMarkupEscaped option isn't set to true. But if it does, it will generate the following HTML without being vulnerable to an XSS attack:

image

Maybe it was so simple and is not what everybody needs ... but it worked for me and maybe for someone else is useful too.

@aidantwoods
Copy link
Collaborator

aidantwoods commented Jun 17, 2017

Hi @sdkcarlos,

Apologies for being blunt here, I'd just like to make sure that no one gets the wrong impression.

it will generate the following HTML without being vulnerable to an XSS attack:

This is not the case. Parsedown is not safe with only setMarkupEscaped enabled.

Parsedown is still vulnerable to XSS attacks other than those introduced by inputting plain HTML tags, because Parsedown does not at present correctly encode data in attributes, nor does it sanitise link destinations (thus allowing use of the javascript: scheme).

I'd highly encourage you to take a look at #495 if you would like a version of Parsedown that is designed to be safe from XSS.

@sdkcarlos
Copy link

Thanks for the suggestion @aidantwoods , i've just updated my composer.json to require your version instead:

{
    "require": {
        "erusev/parsedown": "dev-master#bbb7687f31d6904f3a0e11e97bc61852a62cfe90",
    }
}

now i'm able to use setSafeMode and setMarkupEscaped 👍

@aidantwoods
Copy link
Collaborator

setSafeMode will flip all the switches that setMarkupEscaped would (so no need to set the latter – only setSafeMode is needed). Hopefully we can get that patch merged soon, and out as a proper release (updates are always nice – unfortunately can't really do that with fixed version).

Maybe use the following so that your composer will prefer the next stable Parsedown (once it is available)

"require": {
    "erusev/parsedown": "^1.7.0 || dev-master#bbb7687f31d6904f3a0e11e97bc61852a62cfe90",
}

(Assuming that the minor version would deserve a bump when this new feature is merged, @erusev
could confirm though).

@aidantwoods
Copy link
Collaborator

Hi @sdkcarlos,

I've implemented the anti-xss patch as a Parsedown extension, so you can now instead require aidantwoods/secureparsedown in your composer.json – which has the benefit of keeping both Parsedown and the anti-xss extension up to date.

Hopefully we'll see it in Parsedown core at some point though :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.