Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 784821
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 14, 20262026-05-14T20:46:25+00:00 2026-05-14T20:46:25+00:00

There are many Stack Overflow questions (e.g. Whitelisting, preventing XSS with WMD control in

  • 0

There are many Stack Overflow questions (e.g. Whitelisting, preventing XSS with WMD control in C# and WMD Markdown and server-side) about how to do server-side scrubbing of Markdown produced by the WMD editor to ensure the HTML generated doesn’t contain malicious script, like this:

<img onload="alert('haha');" 
   src="http://www.google.com/intl/en_ALL/images/srpr/logo1w.png" />

But I didn’t find a good way to plug the hole on the client side too. Client validation isn’t a replacement for scrubbing validation on the server of course, since anyone can pretend to be a client and POST you nasty Markdown. And if you’re scrubbing the HTML on the server, an attacker can’t save the bad HTML so no one else will be able to see it later and have their cookies stolen or sessions hijacked by the bad script. So there’s a valid case to be made that it may not be worth enforcing no-script rules in the WMD preview pane too.

But imagine an attacker found a way to get malicious Markdown onto the server (e.g. a compromised feed from another site, or content added before an XSS bug was fixed). Your server-side whitelist applied when translating markdown to HTML would normally prevent that bad Markdown from being shown to users. But if the attacker could get someone to edit the page (e.g. by posting another entry saying the malicious entry had a broken link and asking someone to fix it), then anyone who edits the page gets their cookies hijacked. This is admittedly a corner case, but it still may be worth defending against.

Also, it’s probably a bad idea to allow the client preview window to allow different HTML than your server will allow.

The Stack Overflow team has plugged this hole by making changes to WMD. How did they do it?

[NOTE: I already figured this out, but it required some tricky JavaScript debugging, so I’m answering my own question here to help others who may want to do ths same thing].

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-14T20:46:25+00:00Added an answer on May 14, 2026 at 8:46 pm

    One possible fix is in wmd.js, in the pushPreviewHtml() method. Here’s the original code from the Stack Overflow version of WMD on GitHub:

    if (wmd.panels.preview) {
        wmd.panels.preview.innerHTML = text; 
    }
    

    You can replace it with some scrubbing code. Here’s an adaptation of the code that Stack Overflow uses in response to this post, which restricts to a whitelist of tags, and for IMG and A elements, restricts to a whitelist of attributes (and in a specific order too!). See the Meta Stack Overflow post What HTML tags are allowed on Stack Overflow, Server Fault, and Super User? for more info on the whitelist.

    Note: this code can certainly be improved, e.g. to allow whitelisted attributes in any order. It also disallows mailto: URLs which is probably a good thing on Internet sites but on your own intranet site it may not be the best approach.

    if (wmd.panels.preview) {
    
        // Original WMD code allowed JavaScript injection, like this:
        //    <img src="http://www.google.com/intl/en_ALL/images/srpr/logo1w.png" onload="alert('haha');"/>
        // Now, we first ensure elements (and attributes of IMG and A elements) are in a whitelist,
        // and if not in whitelist, replace with blanks in preview to prevent XSS attacks 
        // when editing malicious Markdown.
        var okTags = /^(<\/?(b|blockquote|code|del|dd|dl|dt|em|h1|h2|h3|i|kbd|li|ol|p|pre|s|sup|sub|strong|strike|ul)>|<(br|hr)\s?\/?>)$/i;
        var okLinks = /^(<a\shref="(\#\d+|(https?|ftp):\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+)"(\stitle="[^"<>]+")?\s?>|<\/a>)$/i;
        var okImg = /^(<img\ssrc="https?:(\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+)"(\swidth="\d{1,3}")?(\sheight="\d{1,3}")?(\salt="[^"<>]*")?(\stitle="[^"<>]*")?\s?\/?>)$/i;
        text = text.replace(/<[^<>]*>?/gi, function (tag) {
            return (tag.match(okTags) || tag.match(okLinks) || tag.match(okImg)) ? tag : ""
        })
    
        wmd.panels.preview.innerHTML = text;  // Original code 
    }
    

    Also note that this fix is not in the Stack Overflow version of WMD on GitHub— clearly the change was made later and not checked back into GitHub.

    UPDATE: in order to avoid breaking the feature where hyperlinks are auto-created when you type in a URL, you also will need to make changes to showdown.js, like below:

    Original code:

    var _DoAutoLinks = function(text) {
    
        text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");
    
        // Email addresses: <address@domain.foo>
    
        /*
            text = text.replace(/
                <
                (?:mailto:)?
                (
                    [-.\w]+
                    \@
                    [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
                )
                >
            /gi, _DoAutoLinks_callback());
        */
        text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
            function(wholeMatch,m1) {
                return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
            }
        );
    
        return text;
    }
    

    Fixed code:

    var _DoAutoLinks = function(text) {
        // use simplified format for links, to enable whitelisting link attributes
        text = text.replace(/(^|\s)(https?|ftp)(:\/\/[-A-Z0-9+&@#\/%?=~_|\[\]\(\)!:,\.;]*[-A-Z0-9+&@#\/%=~_|\[\]])($|\W)/gi, "$1<$2$3>$4");
        text = text.replace(/<((https?|ftp):[^'">\s]+)>/gi, '<a href="$1">$1</a>');
        return text;
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

There are many skills a programmer could have (understanding the problem, asking good questions,
There are many ASP.MVC blog post bits and pieces scattered over different web sites,
There are many ways of doing debugging, using a debugger is one, but the
There are many techniques to enforce strong passwords on website: Requesting that passwords pass
There are many tools out there for writing and managing requirements, but are there
There are many different styles of variable names that I've come across over the
There are many editions of Eclipse for Java development. I am trying out MyEclipse
There are many drawbacks to using void * in C (memory related, type related,
There are many usability evaluation techniques that have been developed over the history of
There are many types of external dependencies. Interfacing with external applications, components or services

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.