 I did pick Muse for a second. I was like, what song did I pick? So yeah, it was Muse. Welcome to this magic course where we're going to talk about something very serious in a very, very unserious way. So my name is Ingrid. I work as an engineer for Intercom. And you can find me as Ingrid E on GitHub and various others in internet places, except for Twitter, because they're not very good at doing name recycling. I love talking about a lot of different things, like coffee and culture and tech, and music, and yoga. So if you're interested about any of that, come find me after the talk. And let's nerd together about all that. And I currently live and work in Dublin, Ireland, but I'm Romanian, which means I get to make a lot of jokes about being a vampire. And there may or may not be an actual gif of me dressed like a vampire doing a zipline over Dublin for the Bram Stalker Festival. So may or may not, in which I may or may not wish that I don't die, because I was very afraid of heights at the time. But today we're not going to talk about that. Today we're going to talk about something equally as fun, which is security, probably to put you better to sleep after lunch, or secure the show to the view and ruin your faith in humanity, whichever one comes first. So yeah, throughout the talk, I do solemnly swear that I'll be up to no good. We'll see how it's going to go. Cool. So a little bit of a story time just to kick off this talk on security. I'm going to tell you a little bit about my favorite owner, Belgi. So it all happened in 2008, and that was a really good year for tech and web. Google released Chrome, and everyone was very excited about that competitor for Firefox. So do I love Firefox. HTML5 was introduced, and the first ever Android device was released. It was also a very interesting year for the security community, because some people discovered a way to embed a jar file, an executable jar file into a gif. And that caused quite a bit of a stir, because no one expected that an image would cause such a big vulnerability. And Java's quite a powerful language, so you can only imagine the extent of this. In 2012, people didn't completely abandon the idea of using crazy things like images to attack users. So they went ahead and discovered a way to embed actual executable code, not just archives, into images. And they created something called an image.js, an image.js attack. And in the example there, I'm pretty much embedding like a PHP script into an image, and I'm taking advantage of the fact that the browser knows that your file is an image just by looking at the header. And then there's a bunch of blob of just nothingness junk that the browser ignores, and then there's the actual content that makes the image. So in that blob of junk, you can pretty much put anything there, and this is a script that says, hey, it's a lovely day, isn't it? So let's see why that is bad. Well, say I have an app that allows users to create and upload those sorts of content, for example, images, there's nothing stopping an attacker from uploading this image into a very nice URL. So just kitten-skitten.jpeg, and then link it to, well, the same URL, except at the end of it, instead of jpeg, we have .jpeg.php. So assuming that that website is actually running PHP, when I click on the link, well, yes, what would happen? My script would run. And instead of being able to download this cute kit kitten image, you're just saying, hey, friend, from IP, it's a lovely Monday afternoon, isn't it? This was actually in my hotel yesterday, so that's why it's Monday, and that's the actual IP of the hotel. So if you wanna play with this, see how it works, I have just on GitHub with all of that. What's particularly bad is if you notice the URL, it's actually running a script that it shouldn't. Under a website that, well, it should do something else, right? And that's bad because something called the same origin policy, which if you don't know what it is, I strongly recommend you do some reading on it, but it's one of the most important web application security policies and ideas, and it basically allows, it tells the browser that if a script runs on the same origin as the website that you're on, then it should have access to all sorts of crazy information, like, well, let's just say your user data, which is pretty serious, and it allows, it's what allows people to impersonate you, right? So yes, cats are planning to kill you, or at least steal your identity and your money very soon, which is very sad because I love cats. But it kinda goes to my point of like, you never know what people are gonna come up with and they're quite inventive in ways that they're gonna attack your app, so you never know. And it plays very nicely to the first rule of web security, which is never, ever, ever trust users to metadata, ever. There's no guarantees, it doesn't matter if it's an image or sound or anything, just never, ever trust it. Okay, part two of the story, I'm gonna tell you a little bit more about Intercom. So in Intercom, we have a four-year-old Ember app, and if we look at the stats from, just kind of understand the magnitude of this, if we look at some stats from last week, we have 37 authors that submitted a total of 190 commits to master, 220 across all branches, which resulted in a total of 892 file changes with more than 5,800 editions and almost 16K deletion, so it's a pretty big app. And on top of that, shipping is at the hard beat of Intercom, so we are shipping to production more than 100 times a day. The backend of our app is Rails, so everything that we're gonna talk about today, I'm gonna try to talk from the perspective of a very mature app. A little bit about me, in 2016, I started working with Ember, and about two months later, I had to fix an issue around uploading in real-time preview of an image without introducing an excess vulnerability in the code. Now, my background is in-fry and backend, so I kind of went like, this is all this mean, especially because our app is huge, and decided to look more into it, and I guess, well, here we are today. So this talk is gonna be too late, didn't read that I list of things that I wish I had back then. Some ranting about linters, and the regular expressions, and a way in which I think engineers can help with the security of an application. So again, all put into the context of a very mature Ember application. Well, so the first thing that you do when you don't know what to do is prepare for battle, and get to know a little bit more about your enemy, and what all of this means. So something that I think is really, really important, before you start, and before you dive into something that's very theoretical, because security tends to be that way, is know a little bit about user input, and understand what you expect from your users. And then know a little bit about the same origin policy, because everything that executes on the web will follow that rule. Know a little bit about the content security policy, and why it's such a powerful tool. We're gonna get into that a little bit later. Know your browsers, know your tools, so the security features on your browsers. And what does HTML as input even mean in Ember? And how does Ember do that? So that's what we're gonna try and focus on today throughout the talk. Oops. So let's look a little bit into what a vulnerability, like where an injection attack actually looks like. So say we have the CPI that allows me to search for coffee, and then it returns a list of results that are displayed in your browser. And the top of that list is just something like results for coffee. And an attacker sees that and kind of goes like, that coffee matches the search term that the user, that I submit it. So I wonder what would happen if I actually use a script to search for it. Now in the modern browsers, if you just do a script alert, the browser is smart enough to say, hey, you probably shouldn't be doing that, it's gonna block it. However, in older versions of the browsers, by older, I mean like about a year ago, Henternite Explorer was still struggling with this. So if instead of passing just a script with an alert, you'd pass something that's slightly malformed, which is this image tag with like three quotes that doesn't make any sense. The browser is gonna go, I don't know what to do with that, so I'm just gonna run it. So, yep, yep, it's not scary at all. So it actually runs, and you know, when you have an alert, you don't really care. I mean, it's a bad user experience, but it's minor. The real problem is that you can do something like document.cookie, and what document.cookie returns is actually the content of your user document. And that becomes a problem if it's in the wrong hands. So this is something that's called a reflected XSS. This is kind of how it looks like, and you can pretty much just spin up your own server and try this on your own. Cool, so now that we know what we have to deal with, let's prepare our spells and look a bit into how we can address all this. The first thing that we're gonna look at is Ember. We are a modern web application, so we wanna use a modern framework, right? And in this case, we're using Ember. So it's very important to know how Ember does HTML escaping and how it deals with user content. And then we're gonna look a little bit into the content security policy and why it's so powerful. So what Ember does as a way to protect you against injection vulnerabilities is actually, by default, escape all the HTML. So the Ember rendering layer, whenever you basically return a piece of HTML from your helper, because why not, you can. It's gonna go, I don't think you wanna do what you think you wanna do, so I'm gonna escape it for you just to keep you safe. And that looks pretty much like this. So if I have a helper that returns a cat image, and I'm returning just the image tag with the source as it is, Ember's gonna go, nope. So instead of seeing a cat image, you're just gonna see the string of what you returned. If you wanna see an actual cat image, you have to tell Ember explicitly that that HTML is safe to display. And you can do that with Ember string HTML safe, which is also a very bad thing that you shouldn't be doing, and we're gonna get into that a little bit later. But if you want to, you can. So when you're doing that, Ember says, oh, we actually wanted an image. And it's gonna show you the image of a cat reading military strategy, which is pretty much what we're doing right now, I guess. And again, there's a just don't get hopes if you wanna play with this, how it works. It's all there. Cool, so now that we know a little bit about Ember, what the hell is the content security policy? Well, in 2004, people kind of went, I'm kind of tired of the sexist attack. Is there a way to mark what is safe to run and what is not? So the guys at Firefox, yay Firefox, were the first one to implement like a somewhat version of the version one content security policy. And then other, it became really popular and other browsers became interested. So in 2012, they actually went on and released the first version of it. And it's a very powerful and very good way to say this script is safe to run and everything else is not. So you can whitelist what your app considers to be safe. The content security policy gets returned pretty much as a header in a HTTP request that tells the browser, hey, here's a list of scripts that I think are safe and the browser is gonna read that and say, oh, okay, so everything from self and starting my site.com is safe. I see someone's trying to embed this pure evil. I'm gonna go ahead and block that because that looks wrong and it's not part of your security policy. The very powerful thing about it is that it will also stop you from, it will also stop inline script, which is the last example when someone's trying to run a script as a, picking it as an image. So it too late didn't read because this is kind of a talk on its own. There's an number CLI add-on from Robert Jackson that like if you don't have a, usually the content security policy is something that you take care of at the server side. But if you're just running a number app and that said, go read that, it's very powerful. It's a pretty good tool. And keep in mind to always use the content security policy version two and version three. Version one was a little bit of an interesting conversation where people couldn't decide what inline script shouldn't do so it's a little bit of a mayhem. Just to be safe through that. But version two was like, I know how to fix it so they introduced hashing and ways to validate that inline script is what it is. And there's a really good documentation about it so the content security policy and like the consortium did a very good job at putting together documentation so you can go ahead and do a bit of reading on that. Cool, so with our theory in mind, let's see how we write better code, right? Because that's kind of the point of all of this. So we're gonna look into eradicating HTML safe and writing better helpers. So you should avoid HTML safe at all costs. Why? Well, because you can never really vouch for the content that your user is gonna submit. You have to make a lot of assumptions and that's pretty scary. And the risk of missing something increases with the number of assumptions that you're gonna make. So a better way to not worry about it, try to avoid HTML safe and figure out better ways to rewrite your code. Never use directly on user input, duh. And your controller should not hit HTML, ever. You shouldn't have HTML on your controller. It doesn't belong there. And as a power up, there's contextual components. So let's say I wanna just write a very simple card component that has a title and a content. And that works for a very long time and then someone comes along and says, hey, I actually wanna name input and I wanna say hi to that person in the title. Can you do that? And the answer is, well, you can. And for a very long time, this was the way this was addressed. Well, you'd have just a card component that takes a title and then the content part of it. And then in your controller, you'd say, okay, I want my name to be displayed with bold. So it's gonna return a HTML safe, hi, name and bold. And that's it. And that is pretty bad because it potentially, it could potentially introduce a vulnerability. You have no control over what your name is. So a better way to rewrite this is using contextual components. And again, this can probably be a talk or a tutorial on its own. So I'm gonna give you the basic and then if you wanna read about it a little bit more, there's the Ember map. Has a really good tutorial on that. So I'm gonna rewrite my component using these yielded properties so then I can access the card title and the card body directly. And the reason why I wanna do that is because the title and the body have two separate functions, right? And two separate roles. And I wanna be able to be a little bit more opinionated about that. And if I want the title to be just a simple string, then I can do that. And if I want the title to do something crazy, like say hello to a person, then I can do that as well. So I'm just using the card properties, the title and the body to just tell them what to do. And it's gonna look something like hi Hermione and bold and just a text, well done Harry, this looks significantly better. If we look at our super card component and how that is implemented, it uses this hash helper to actually yield two components. One component for the title that will take care of displaying Hermione or Embercon for whatever we want in there. And then a body that will just yield whatever content we want as well. And if this component gets a title as well, then it's just gonna call the title component with that title and let the component take care of that. So it becomes so much simpler. In our body, we don't wanna do anything fancy, we just wanna yield whatever content we have. And then on our title component, on the child title component, if it has a block, so if I just wanna display something very simple like hello, I'm very excited to be here, which is true, then I'm just gonna yield that content. And if I need anything, if I have something more complicated like HTML, then I can do that as well. Cool, so that takes care of using the name and the title. If, like I said before, if I just want something very simple, which is EmberConf, then I can just pass the title to the supercard component and have it take care of how to display it and where to display it. So I don't have to tell Ember what things are safe to display and where it should be anymore. It's gonna take care of that itself. And I'm just calling the, so card.body and passing the whatever content that I want displayed on the body because I already have a title. So it's just a much nicer, much more deliberate way of displaying content and it involves less hacking to be able to accommodate future usages. So if I wanna change this into displaying an image or whatever the hell I wanna do after that, it's very easy to do it with this. I don't have to worry about it anymore. So contextual components are quite powerful. I feel very bad that I'm not able to cover more of this, but do go and do some reading on them, they're awesome, and allow this to lower the number of HTML saves in our app. Cool. Something that's also very important is writing with helpers. If you remember my very cute cat image that returns HTML, ideally you should prefer updating DOM over having HTML and helpers. And say, let's say you wanna write something that takes a, wants to return a user email or a helper to allow you to like send an email. Well, the way you'd previously do this is that you'd have to sanitize the user input to make sure that there's nothing crazy going on there. And then you'd have to use HTML save to tell Amber that, hey, this is actual HTML, I vouch for this and you shouldn't touch it. And that's kinda scary. Because you cannot, like, it can introduce unexpected behavior and again it runs on you making assumptions about your content. So much better way to do this is to use the DOM directly to create a text node. And then set the style attributes if you have to because you can and it's very simple. And then append, let's say you have an anchor in this case, so append the anchor child element, return the node and then that's it. So let's look at the way that, let's look how, what all this means in code, right? So you have this good mail to helper and it takes a parameter and email name and a class if you wanna style that email. And then I'm going ahead and creating an anchor tag element. I'm setting the target to blank, I'm setting the reference to the user email, I'm setting a class name if that was provided as a parameter. And then all the magic is when I'm creating the text, so I'm creating this element as a text node and letting the browser take care of all the escaping and all the displaying and just say, hey, browser, always treat this as text rather than me having to like be deliberate of is it HTML or is it text or whatever. So just don't worry about it, just don't worry about it. And then I'm appending the child, the text child to A and then just returning it. And it's a much nicer way to, again, just worry less. Worrying less is good. Cool, so now we know how to write really, we know how to write better components and we know how to write better helpers. But we have templates as well. And turns out you can escape HTML on your templates. And we're gonna also talk a little bit about target blank and what that means and why it's a very bad idea to use on its own. So escaping, we've already kind of established that escaping HTML is very dangerous. And what triple Curly's is basically HTML save for templates. And you should never use directly on the user input. And in fact, you should be always deliberate and mindful about what you vouch for. But the reality of it is that you should never ever have to find yourself in a situation where you have triple Curly's. If you do, then you should probably consider refactoring some code with contextual components and good helpers in mind. And good helpers plus contextual components would actually allow you to not have to have triple Curly's in your code anymore. And if you do, please go and refactor it. Target blank is probably one of the most underestimated vulnerabilities in the security community. And I guess the Too Late Didn't Read rule about this is that you should always use target blank with no opener and no refer as attributes. And the reason for that is when you specify target blank, that tells your browser that, hey, the next page should have access to a bunch of window objects, especially window object and window, sorry, window opener and window opener location. So it allows the page that you're linking to to have access to the location and change it if you want to to pretty much whatever it wants. It can be a phishing website, can be something completely safe, it can be something completely unsafe. Some of the permissions will automatically be negated by the same origin policy. So if it's a different origin that it won't have access to your cookies or anything crazy like that. But window location is fair game. And it's a very good way for people to redirect you to whatever website they want. The problem with this is that browsers tend to have different opinions when it comes to no opener and no refer. And by that I mean that Firefox decided to not implement no opener until well version 54 that's gonna be released at the end of this month. So if you only have one of them in your code, then you're actually letting users that prefer browser over the other a little unprotected. And what's even funny is that Instagram suffered from this vulnerability until last year when someone wrote a very raging blog post that became super famous overnight and went hey, Instagram, could you actually fix your stuff? So this is how, so to make sure that your, if you support Firefox or large range of browsers, then you should always use realm no opener and no refer in your templates. And a very good way to detect that is using the Ember template lint by Robert Jackson. And for those of you that are familiar with this, the linter used to validate for no opener or no refer. And there's been a patch submitted this week to actually validate both. So all you have to do is make sure that you're on the latest version and then switch from truth to strict and make sure that you also like fix your code if that's the case. Otherwise you're gonna see a bunch of errors. But it's gonna allow you to make sure that both your users are protected. And it also provides detection for triple curlies. So it's quite a powerful add-on. I strongly recommend you go and add it to your project. Cool, now that our code is a little bit better, how do we keep it that way? So I'm gonna talk a little bit about static analyzers which is my favorite thing to rant about these days. And we're gonna talk about ESLint. We're gonna talk about why regular expressions are evil and I hate them with passion. And why setting watermarks or like lines in the sand for like where you are from a security point of view is a very good and very sane thing. So first the story. Before ESLint there was grep. So we had this idea of checking for the occurrences of HTML safe in our code using grep because you can. And we built a tiny add-on that uses a post-built hook to get real-time feedback in dev about whatever it is that you wanna check. So it's a combination of find plus grep plus regular expressions plus WC minus out so word count lines. And compare the count against the static limit that's been preset. So say you have HTML safe five and now when it runs, if HTML safe is at six then you have a problem. And then fail the build if the numbers don't match. And this was built with getting engineers real-time feedback in dev and giving them an opportunity to address those changes especially if it involves refactoring you don't wanna find out about it when you're running NCI you really don't especially if you have to fix something and fix it fast. And that worked fine but hey regular expressions are a little bit like black magic and you do kind of have to sell your soul a little bit to understand them. I know there's people doing crazy things with regular expressions in Perl I won't go into that. But personally and the reality of it is whenever you have a regular expression it makes that much harder to maintain your code. So it does work it as fast but it's not ideal. So we looked into a way to do this a little bit better using Geass Lint. And we thought hey could we maybe use Lint-ers for real-time feedback and figure out a way to like plug it all in and have the same line in the sand but instead of using grep using Lint-ers to make it a little bit more maintainable. The problem with this is that Lint-ers are notoriously or could be notoriously slow especially when you run them on thousands of files. So we definitely didn't our main concern for this was would the Lint-er be fast enough to be able to run real-time in dev. So the main idea was to write a customer rule that checks for blacklisted methods. So it would get an argument of a list of blacklisted methods that you want to check for like HTML safe. And then use the ESLint running engine to get account for that. So the ESLint for those of you that are not familiar with it relies on something called an ASD tree and then it parses that tree and checks for whatever it is that you're interested in. So in our case it's a function which makes it a call expression in ESLintLand. And it's looping through all the blacklisted methods that you got as an argument. And if it finds one it's gonna throw an error saying hey this method has actually been blacklisted and you shouldn't use it. Cool, so now we have the rule that runs that. How does it actually, how is it gonna run, right, in the code? So we're gonna use the ESLint CLI API plus the customer rule that we just built to get the accounts for different blacklisted methods. And then allowing ESLint to actually cache, so in dev to actually cache all the runs to make it faster. And it turns out it's actually like the performance difference of like using cache and not using caches between 10 to something crazy like 60 seconds on slower machines. So caching is something that's very, very important for ESLint, which means yes on a colder build you're gonna have some issues, but if you're not running for the first time you should get quite good performance results with caching. And then fail to build if the error count is bigger than the max allow. And this is kind of what it looks like when you run in dev. So the first time there's no problem, his runs is just fine, and then I'm updating this new.js and using HTML safe because I don't know any better. And then I see a big red error on the screen going, hey, actually you've just introduced a new HTML safe vulnerability, you probably shouldn't do that. So it allows the engineer to go, oh, actually fair enough, and go and refactor the code, make the change, and then it rebuilds. If you're looking at the rebuild time we're at 1.3 seconds I think. So it is pretty fast to be used in dev and you can also, this is just taking advantage of the post build hook, but there's nothing stopping you from running it in CI as well. So if you don't really wanna deal with configuring all this, we are working on an add-on to blacklist methods. So I guess following on Twitter or intercom engineering again, there's gonna be more news about this in the following days. So yep, we got your back. Now that your code is better you have a lot of information to keep going, you know what to do. It's generally a really good idea to like throw an eye in the community and see what happens and basically consult with other wizards. A really good resource is the OS top 10. What they do is check every year and create a top 10 of like the most common vulnerabilities. Shocking excess is still at the top of the list. And then broken identification and session management was used to be, I think not on this list, we're at the very bottom of this list about three years ago and now it's at the very top. So that should probably make a lot of people start worrying. And something else that we've done is run bug bounties in intercom. So up until February 2016, we had a private bug bounty and now it's a public one. It's a very good way to invite security experts to test your code and get a better understanding of where you are. So thank you very much.