sails
Version:
API-driven framework for building realtime apps, using MVC conventions (based on Express and Socket.io)
111 lines (76 loc) • 3.55 kB
Markdown
# XSS
Cross-site scripting (XSS) is a type of attack in which a malicious agent manages to inject client-side JavaScript into your website, so that it runs in the trusted environment of your users' browsers.
### Protecting against XSS attacks
The cleanest way to prevent XSS attacks is to escape untrusted data _at the point of injection_. That means at the point where it's actually being injected into the HTML.
#### On the server
##### When injecting data into a server-side view...
Use `<%= %>` to HTML-encode data:
```html
<h3 is="welcome-msg">Hello <%= me.username %>!</h3>
<h4><%= owner.username %>'s projects:</h4>
<ul><% _.each(projects, function (project) { %>
<li>
<a href="/<%= owner.username %>/<%= project.slug %>"><%= project.friendlyName %></a>
</li>
<% }); %></ul>
```
##### When exposing view locals to client-side JavaScript...
Use the `exposeLocalsToBrowser` partial to safely expose some or all of your view locals to client-side JavaScript:
```html
<%- exposeLocalsToBrowser(); %>
<script>
console.log(window.SAILS_LOCALS);
// {
// me: {
// username: 'eleven',
// memberSince: '1982-08-01T05:00:00.000Z'
// },
// owner: {
// username: 'joyce',
// memberSince: '1987-11-03T05:00:00.000Z'
// },
// projects: [
// {
// slug: 'my-neat-stuff-n-things',
// friendlyName: 'My neat stuff & things',
// description: 'Yet another project.'
// },
// {
// slug: 'kind-of-neat-stuff-but-not-that-great',
// friendlyName: 'Kind of neat stuff, but not that great...',
// description: 'I am so sick and tired of these project. <script>alert(\'attack\');</script>'
// }
// ],
// _csrf: 'oon95Uac-wKfWQKC5pHx1rP3HsiN9tjqGMyE'
// }
</script>
```
> Note that when you use this strategy, the strings in your view locals are no longer HTML unescaped after being exposed to client-side JavaScript.
> That's because you'll want to escape them _again_ when you stick them in the DOM. If you always escape at the point of injection, this stuff is a
> lot easier to keep track of. This way, you know you can safely escape _any_ string you inject into the DOM from your client-side JavaScript.
> (More on that below.)
#### On the client
A lot of XSS prevention is about what you do in your client-side code. Here are a few examples:
##### When injecting data into a client-side JST template...
Use `<%- %>` to HTML-encode data:
```html
<div data-template-id="welcome-box">
<h3 is="welcome-msg">Hello <%- me.username %>!</h3>
</div>
```
##### When modifying the DOM with client-side JavaScript...
Use something like `$(...).text()` to HTML-encode data:
```js
var $welcomeMsg = $('#signup').find('[is="welcome-msg"]');
welcomeMsg.text('Hello, '+window.SAILS_LOCALS.me.username+'!');
// Avoid using `$(...).html()` to inject untrusted data.
// Even if you know an XSS is not possible under particular circumstances,
// accidental escaping issues can cause really, really annoying client-side bugs.
```
> As you've probably figured out, the example above assumes you are using jQuery, but the same concepts apply regardless of what front-end library you are using.
### Additional Resources
+ [XSS (OWasp)](https://www.owasp.org/index.php/XSS)
+ [XSS Prevention Cheatsheet](https://www.owasp.org/index.php/XSS_Prevention_Cheat_Sheet)
### Notes
> + The examples above assume you are using the default view engine (EJS) and client-side JST/Lodash templates from the default asset pipeline.
<docmeta name="displayName" value="XSS">