874
edits
(Origination) |
(added code examples) |
||
Line 5: | Line 5: | ||
If at all possible, see if you can implement your command using a [[Labs/Ubiquity/Locked-Down_Feed_Tutorial|Locked-Down Feed]]. Not only does it make it harder for any coding mistakes to accidentally harm the user, but it also makes it easier for the end-user to subscribe to, since they're not presented with a big [[Media:Warning.PNG|warning of doom]]. | If at all possible, see if you can implement your command using a [[Labs/Ubiquity/Locked-Down_Feed_Tutorial|Locked-Down Feed]]. Not only does it make it harder for any coding mistakes to accidentally harm the user, but it also makes it easier for the end-user to subscribe to, since they're not presented with a big [[Media:Warning.PNG|warning of doom]]. | ||
=== Untrusted HTML === | |||
Even when you inject untrusted text into a trusted context, make sure it's properly escaped with <tt>[https://ubiquity.mozilla.com/hg/ubiquity-firefox/raw-file/tip/ubiquity/index.html#modules/utils.js Utils.escapeHtml()]</tt>, or else the text could be carefully constructed to execute malicious code. Another alternative is to set an element's text contents using jQuery's <tt>text()</tt> method. | If you use a regular feed, we recommend using the <tt>[https://ubiquity.mozilla.com/hg/ubiquity-firefox/raw-file/tip/ubiquity/index.html#feed-parts/header/cmdutils.js CmdUtils.safePreview()]</tt> function to display any untrusted HTML content to the end-user. If you don't do this and just inject untrusted HTML into the DOM node your preview function is given, then this code will run in a trusted context, which means that malicious or misbehaving code in the HTML can do whatever it wants to your computer. For instance: | ||
<pre> | |||
CmdUtils.CreateCommand({ | |||
... | |||
preview: function preview(pblock) { | |||
Utils.previewGet( | |||
pblock, | |||
"http://www.example.com/somehtml", | |||
null, | |||
// SECURITY RISK: code injection vulnerability | |||
function(html) { pblock.innerHTML = html; }, | |||
"html" | |||
); | |||
}, | |||
... | |||
}); | |||
</pre> | |||
The above code is bad because <code>pblock</code> is a trusted DOM node that's having untrusted HTML injected into it. Wrapping the <code>preview</code> function in <code>CmdUtils.safePreview()</code> resolves the problem: | |||
<pre> | |||
CmdUtils.CreateCommand({ | |||
... | |||
preview: CmdUtils.safePreview(function(pblock) { | |||
Utils.previewGet( | |||
pblock, | |||
"http://www.example.com/somehtml", | |||
null, | |||
// pblock is now an untrusted DOM element, so | |||
// this is okay. | |||
function(html) { pblock.innerHTML = html; }, | |||
"html" | |||
); | |||
}), | |||
... | |||
}); | |||
</pre> | |||
=== Escaping Text === | |||
Even when you inject untrusted text into a trusted context, make sure it's properly escaped with <tt>[https://ubiquity.mozilla.com/hg/ubiquity-firefox/raw-file/tip/ubiquity/index.html#modules/utils.js Utils.escapeHtml()]</tt>, or else the text could be carefully constructed to execute malicious code. For example: | |||
<pre> | |||
CmdUtils.CreateCommand({ | |||
... | |||
preview: function preview(pblock, dobj) { | |||
// SECURITY RISK: Unescaped, untrusted text content. | |||
pblock.innerHTML = "<i>Your</i> direct object is " + dobj.text; | |||
} | |||
... | |||
}); | |||
</pre> | |||
Instead, use <code>Utils.escapeHtml()</code> on the text, like so: | |||
<pre> | |||
CmdUtils.CreateCommand({ | |||
... | |||
preview: function preview(pblock, dobj) { | |||
// SECURITY RISK: Unescaped, untrusted text content. | |||
pblock.innerHTML = ("<i>Your</i> direct object is " + | |||
Utils.escapeHtml(dobj.text)); | |||
} | |||
... | |||
}); | |||
</pre> | |||
Another alternative is to set an element's text contents using jQuery's <tt>text()</tt> method. | |||
== For Core Developers == | == For Core Developers == | ||
Check out the [https://www.owasp.org/index.php?title=XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#You_Need_a_Security_Encoding_Library Cross-Site Scripting Prevention Cheat Sheet Cross-Site Scripting Prevention Cheat Sheet]. Ubiquity's <tt>chrome://</tt> pages—even the ones that just look like web pages—run in a trusted context, but they sometimes display untrusted content, such as text metadata for a Locked-Down feed; therefore we need to make sure that we're escaping the data properly. The stakes here are higher than they are for XSS attacks because rather than the attacker gaining control of a user's web experience on a single domain, they gain control of the user's entire computing experience. | Check out the [https://www.owasp.org/index.php?title=XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#You_Need_a_Security_Encoding_Library Cross-Site Scripting Prevention Cheat Sheet Cross-Site Scripting Prevention Cheat Sheet]. Ubiquity's <tt>chrome://</tt> pages—even the ones that just look like web pages—run in a trusted context, but they sometimes display untrusted content, such as text metadata for a Locked-Down feed; therefore we need to make sure that we're escaping the data properly. The stakes here are higher than they are for XSS attacks because rather than the attacker gaining control of a user's web experience on a single domain, they gain control of the user's entire computing experience. |
edits